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

Added Custom Headers Logic to Query #9458

Conversation

srijantrpth
Copy link
Contributor

@srijantrpth srijantrpth commented Dec 16, 2024

Proposed Changes

  • Fixes Modify queryRequest to support custom headers #9457
  • Added logic to include Custom Headers in Query Function as a part of new OTP based flow for Scheduling Appointments
  • Merged custom headers with the default headers
  • Updated Function Signature to use Extended query Options.

@ohcnetwork/care-fe-code-reviewers

Merge Checklist

  • Add specs that demonstrate bug / test a new feature.
  • Update product documentation.
  • Ensure that UI text is kept in I18n files.
  • Prep screenshot or demo video for changelog entry, and attach it to issue.
  • Request for Peer Reviews
  • Completion of QA

Summary by CodeRabbit

  • New Features
    • Introduced the ability to specify custom headers for query requests, enhancing flexibility in request management.
    • Added support for dynamic inclusion of additional headers in the request system.
  • Bug Fixes
    • Improved the handling of authorization tokens in headers to ensure correct formatting.
    • Streamlined header management by removing an unnecessary function for obtaining authorization tokens.

@srijantrpth srijantrpth requested a review from a team as a code owner December 16, 2024 12:54
Copy link
Contributor

coderabbitai bot commented Dec 16, 2024

Walkthrough

The changes in the src/Utils/request/query.ts file enhance the management of HTTP headers in requests by introducing an optional headers property in the QueryOptions interface. The queryRequest function is updated to merge default headers with any custom headers provided, allowing for greater flexibility. Additionally, the makeHeaders function now accepts extra headers, and the method for obtaining the authorization token has been streamlined by retrieving it directly from local storage.

Changes

File Change Summary
src/Utils/request/query.ts - Updated queryRequest and query function signatures to manage custom headers
- Modified header construction to merge default and custom headers
src/Utils/request/types.ts - Added optional headers?: HeadersInit; property to QueryOptions<TBody> interface
src/Utils/request/utils.ts - Updated makeHeaders function to include additionalHeaders?: HeadersInit
- Removed getAuthorizationHeader function, replaced with direct token retrieval from localStorage

Assessment against linked issues

Objective Addressed Explanation
Support custom headers in queryRequest [#9457]

Possibly related PRs

Poem

🐰 In code we weave a header's grace,
Custom options now find their place,
With tokens fetched from storage bright,
Our queries dance in pure delight!
Hopping high, our changes sing,
To flexible requests, let us bring! 🌟


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 596168e and f897a9f.

📒 Files selected for processing (2)
  • src/Utils/request/query.ts (1 hunks)
  • src/Utils/request/utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Utils/request/query.ts
  • src/Utils/request/utils.ts

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.

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

netlify bot commented Dec 16, 2024

Deploy Preview for care-ohc ready!

Name Link
🔨 Latest commit f897a9f
🔍 Latest deploy log https://app.netlify.com/sites/care-ohc/deploys/676046c3e3da3a000841a2c4
😎 Deploy Preview https://deploy-preview-9458--care-ohc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

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 (2)
src/Utils/request/query.ts (2)

8-11: LGTM! Consider documenting the interface.

The interface extension is well-designed and maintains backward compatibility. The Record<string, string> type is appropriate for HTTP headers.

Consider adding JSDoc comments to document the purpose and usage of this interface, especially since it's exported:

+/**
+ * Extends QueryOptions to support custom HTTP headers
+ * @template TBody - The type of the request body
+ */
export interface ExtendedQueryOptions<TBody> extends QueryOptions<TBody> {
  customHeaders?: Record<string, string>;
}

61-62: LGTM! Consider improving type safety.

The function signature update correctly incorporates the new ExtendedQueryOptions while maintaining existing functionality.

Consider making the signal parameter type more explicit:

-export default function query<TData, TBody>(
+export default function query<TData, TBody, TError = unknown>(
   route: Route<TData, TBody>,
   options?: ExtendedQueryOptions<TBody>,
-) {
-  return ({ signal }: { signal: AbortSignal }) => {
+): (params: { signal: AbortSignal }) => Promise<TData> {
+  return ({ signal }) => {
     return queryRequest(route, { ...options, signal });
   };
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 96bc802 and f6c40d2.

📒 Files selected for processing (1)
  • src/Utils/request/query.ts (2 hunks)
🔇 Additional comments (1)
src/Utils/request/query.ts (1)

14-15: Verify compatibility with existing query usages.

Since this changes the signature of a widely-used utility function, we should verify that existing usages remain compatible.

✅ Verification successful

Let me try a different search pattern since the previous one might have been too restrictive.


Based on the search results, I can now generate the final response:

The changes to the query function interface are safe and compatible

The codebase search reveals that all existing usages of the query function follow the updated interface pattern:

  • All calls pass a route object as the first parameter
  • The second options parameter is consistently optional and matches the ExtendedQueryOptions type
  • The Route type is properly used across the codebase with consistent generic parameters
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all query function imports and usages
echo "Checking query function imports:"
rg -l "import.*query.*from.*['\"]@/Utils/request/query" 

echo "\nChecking query function usages:"
ast-grep --pattern 'query({
  $$$
})'

Length of output: 279


Script:

#!/bin/bash
# Search for query function imports with more relaxed pattern
echo "Checking query imports:"
rg "import.*query.*from.*['\"].*request" -A 2

echo "\nChecking direct query usages:"
rg "query\(" -A 2

# Also check for the Route type usage
echo "\nChecking Route type usage:"
rg "Route<" -A 2

Length of output: 4820

Comment on lines 19 to 23
// Merge customHeaders with default headers
const headers = {
...makeHeaders(noAuth ?? false),
...(options?.customHeaders || {}),
};
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 16, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add validation for custom headers to prevent security issues.

While the header merging logic is correct, the lack of validation on custom headers could lead to security issues, especially since this is part of an OTP-based authentication flow.

Consider adding validation before merging headers:

+ // Validate custom headers to prevent injection
+ const sanitizeHeaders = (headers: Record<string, string>) => {
+   const sanitized: Record<string, string> = {};
+   for (const [key, value] of Object.entries(headers)) {
+     // Ensure header names and values follow RFC 7230
+     if (/^[!#$%&'*+-.^_`|~0-9a-zA-Z]+$/.test(key) && 
+         typeof value === 'string' &&
+         !value.includes('\n') && 
+         !value.includes('\r')) {
+       sanitized[key] = value;
+     }
+   }
+   return sanitized;
+ };

  const headers = {
    ...makeHeaders(noAuth ?? false),
-   ...(options?.customHeaders || {}),
+   ...sanitizeHeaders(options?.customHeaders || {}),
  };

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

Copy link
Member

Choose a reason for hiding this comment

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

Would using Headers obj. instead help prevent these security issues?

Back with references.

Copy link
Contributor

Choose a reason for hiding this comment

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

@rithviknishad, using the Headers object can help manage HTTP headers more effectively, but it doesn't inherently prevent the security issues associated with unvalidated custom headers. The Headers interface enforces certain constraints on header names and values, which can reduce the risk of malformed headers. However, it doesn't automatically sanitize or validate header content against injection attacks or other security vulnerabilities.

Here's how you might use the Headers object:

const headers = new Headers(makeHeaders(noAuth ?? false));

if (options?.customHeaders) {
  for (const [key, value] of Object.entries(options.customHeaders)) {
    // Optional: Add validation logic here
    headers.set(key, value);
  }
}

While this approach uses the Headers API, it's still important to validate or sanitize any custom headers to ensure they don't introduce security risks.

References:

Comment on lines 8 to 11
// Extend the QueryOptions interface to include customHeaders
export interface ExtendedQueryOptions<TBody> extends QueryOptions<TBody> {
customHeaders?: Record<string, string>;
}
Copy link
Member

Choose a reason for hiding this comment

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

The interface QueryOptions is defined exclusively for this itself. Feel free to move that interface here and directly add custom headers to that interface.

Suggested change
// Extend the QueryOptions interface to include customHeaders
export interface ExtendedQueryOptions<TBody> extends QueryOptions<TBody> {
customHeaders?: Record<string, string>;
}
export interface ExtendedQueryOptions<TBody> extends QueryOptions<TBody> {
headers?: HeadersInit;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made the changes as suggested

Comment on lines 19 to 23
// Merge customHeaders with default headers
const headers = {
...makeHeaders(noAuth ?? false),
...(options?.customHeaders || {}),
};
Copy link
Member

Choose a reason for hiding this comment

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

We could modify the makeHeaders function directly to concat the headers through Headers obj. initialization itself.

Suggested change
// Merge customHeaders with default headers
const headers = {
...makeHeaders(noAuth ?? false),
...(options?.customHeaders || {}),
};
const headers = makeHeaders(noAuth ?? false, additionalHeaders)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made the changes as suggested

@rithviknishad
Copy link
Member

@srijantrpth I've also updated to include improved type-safety for the useQuery's error type. Pushed it along with this since it was a very minor piece.

cc: @Jacobjeevan

Before

image

After

image

@srijantrpth
Copy link
Contributor Author

@rithviknishad Kindly review the changes and let me know if you have any suggestions on improving the solution

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

🧹 Nitpick comments (3)
src/Utils/request/query.ts (3)

17-33: Use the built-in Headers class for header management and validation.

The custom sanitizeHeaders function replicates functionality provided by the Headers interface, which automatically normalizes and validates header names and values according to the HTTP specification. Utilizing Headers can simplify the code and enhance reliability.

Apply this diff to refactor the code:

-// Function to sanitize custom headers
-const sanitizeHeaders = (headers: Record<string, string>) => {
-  const sanitized: Record<string, string> = {};
-  for (const [key, value] of Object.entries(headers)) {
-    // Ensure header names follow RFC 7230 and values are safe
-    if (
-      /^[!#$%&'*+-.^_`|~0-9a-zA-Z]+$/.test(key) &&
-      typeof value === "string" &&
-      !value.includes("\n") &&
-      !value.includes("\r")
-    ) {
-      sanitized[key] = value;
-    }
-  }
-  return sanitized;
-};

 ...

 // Merge default headers with custom headers using Headers interface
-const defaultHeaders = makeHeaders(noAuth ?? false);
-const customHeaders = sanitizeHeaders(options?.customHeaders || {});
-const headers = { ...defaultHeaders, ...customHeaders }; // Merging headers manually
+const headers = makeHeaders(noAuth ?? false, options?.customHeaders);

This approach leverages the Headers class's built-in validation and simplifies header merging.


42-44: Avoid manual header merging; delegate to makeHeaders function.

Manually merging headers can lead to inconsistent behavior. Since makeHeaders already supports additional headers, you can pass options?.customHeaders directly to it.

Apply this change:

-const defaultHeaders = makeHeaders(noAuth ?? false);
-const customHeaders = sanitizeHeaders(options?.customHeaders || {});
-const headers = { ...defaultHeaders, ...customHeaders }; // Merging headers manually
+const headers = makeHeaders(noAuth ?? false, options?.customHeaders);

This ensures consistent header creation and leverages existing utility functions.


85-86: Update the generic type parameters for consistency and clarity.

Ensure that the generic type parameters TData and TBody are consistently applied in the query function signature.

Review and confirm that the usage aligns with intended types. No code changes are necessary if types are correctly applied.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f6c40d2 and 0883fb4.

📒 Files selected for processing (3)
  • src/Utils/request/query.ts (2 hunks)
  • src/Utils/request/types.ts (1 hunks)
  • src/Utils/request/utils.ts (1 hunks)
🔇 Additional comments (1)
src/Utils/request/types.ts (1)

44-44: Redundant headers property in QueryOptions.

The headers?: HeadersInit; property addition to QueryOptions may be unnecessary if custom headers are managed via customHeaders or passed directly to makeHeaders.

This concern is similar to the previous suggestion about simplifying header management.

Comment on lines 12 to 15
export interface QueryOptionsWithHeaders<TBody> extends QueryOptions<TBody> {
customHeaders?: Record<string, string>;
headers?: HeadersInit;
}
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 16, 2024

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider extending existing QueryOptions instead of creating a new interface.

The addition of QueryOptionsWithHeaders<TBody> introduces redundancy since headers have already been added to QueryOptions<TBody> in types.ts. You can simplify the code by using QueryOptions<TBody> directly and removing QueryOptionsWithHeaders<TBody>.

Apply this diff to remove the redundant interface:

-/**
- * Extend the QueryOptions interface to include customHeaders
- * @template TBody - The type of the request body
- */
-export interface QueryOptionsWithHeaders<TBody> extends QueryOptions<TBody> {
-  customHeaders?: Record<string, string>;
-  headers?: HeadersInit;
-}

And update the function signatures accordingly:

 async function queryRequest<TData, TBody>(
   { path, method, noAuth }: Route<TData, TBody>,
-  options?: QueryOptionsWithHeaders<TBody>,
+  options?: QueryOptions<TBody>,
 ): Promise<TData> { ... }

 export default function query<TData, TBody>(
   route: Route<TData, TBody>,
-  options?: QueryOptionsWithHeaders<TBody>,
+  options?: QueryOptions<TBody>,
 ): (params: { signal: AbortSignal }) => Promise<TData> { ... }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixing it

Copy link
Contributor

Choose a reason for hiding this comment

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

@srijantrpth, thank you for fixing it!


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

src/Utils/request/utils.ts Outdated Show resolved Hide resolved
src/Utils/request/utils.ts Show resolved Hide resolved
@srijantrpth srijantrpth marked this pull request as draft December 16, 2024 13:37
@rithviknishad
Copy link
Member

I think the santizie headers is an overkill. Since we are anyways not going to take user input for setting the header values.

cc: @Jacobjeevan

@srijantrpth
Copy link
Contributor Author

@rithviknishad So should we remove the sanitizeHeaders?

@github-actions github-actions bot added needs-triage question Further information is requested labels Dec 16, 2024
@Jacobjeevan
Copy link
Contributor

@rithviknishad So should we remove the sanitizeHeaders?

yep

@srijantrpth
Copy link
Contributor Author

@rithviknishad So should we remove the sanitizeHeaders?

yep

Ok, I am implementing the overwriting in the headers.

@rithviknishad rithviknishad removed question Further information is requested needs-triage labels Dec 16, 2024
@srijantrpth
Copy link
Contributor Author

@rithviknishad Something is wrong with cypress tests maybe there's a version mismatch

@srijantrpth srijantrpth marked this pull request as ready for review December 16, 2024 14:57
@srijantrpth
Copy link
Contributor Author

srijantrpth commented Dec 16, 2024

@rithviknishad Something is wrong with cypress tests due to version maybe due to the version

@github-actions github-actions bot added needs-triage question Further information is requested labels Dec 16, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/Utils/request/query.ts (1)

Line range hint 47-51: Improve error handling with more specific error messages.

The current generic "Network Error" message doesn't provide enough context about what went wrong.

Consider enhancing the error handling:

  try {
    res = await fetch(url, fetchOptions);
  } catch (error) {
-   throw new Error("Network Error");
+   throw new QueryError({
+     message: error instanceof Error ? error.message : "Network Error",
+     status: 0,
+     silent: options?.silent ?? false,
+     cause: { type: "network_error", details: error },
+   });
  }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0883fb4 and 0f74197.

📒 Files selected for processing (1)
  • src/Utils/request/query.ts (1 hunks)
🔇 Additional comments (1)
src/Utils/request/query.ts (1)

30-34: Verify the impact of header changes across the codebase.

The changes to header handling might affect existing code that relies on the previous behavior.

Let's verify the usage:

Comment on lines 10 to 17
export interface QueryOptions<TBody> {
body?: TBody;
queryParams?: Record<string, any>;
pathParams?: Record<string, any>;
silent?: boolean;
signal?: AbortSignal;
headers?: Record<string, string>; // Add headers support
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use HeadersInit type for better compatibility with the Fetch API.

The headers property type should be HeadersInit instead of Record<string, string> for better compatibility with the Fetch API's Headers interface.

Apply this diff:

  export interface QueryOptions<TBody> {
    body?: TBody;
    queryParams?: Record<string, any>;
    pathParams?: Record<string, any>;
    silent?: boolean;
    signal?: AbortSignal;
-   headers?: Record<string, string>; // Add headers support
+   headers?: HeadersInit; // Add headers support
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface QueryOptions<TBody> {
body?: TBody;
queryParams?: Record<string, any>;
pathParams?: Record<string, any>;
silent?: boolean;
signal?: AbortSignal;
headers?: Record<string, string>; // Add headers support
}
export interface QueryOptions<TBody> {
body?: TBody;
queryParams?: Record<string, any>;
pathParams?: Record<string, any>;
silent?: boolean;
signal?: AbortSignal;
headers?: HeadersInit; // Add headers support
}

Comment on lines 25 to 34
// Convert Headers object to a plain object
const defaultHeaders = Object.fromEntries(
makeHeaders(noAuth ?? false).entries(),
);

// Merge default headers with custom headers, with custom headers taking precedence
const headers = {
...defaultHeaders,
...(options?.headers || {}),
};
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 16, 2024

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve header handling using the Headers API.

The current implementation converts Headers to a plain object and then merges them, which:

  1. Loses the built-in validation and normalization of the Headers API
  2. Makes it harder to handle multiple values for the same header

Consider using the Headers API directly:

-  // Convert Headers object to a plain object
-  const defaultHeaders = Object.fromEntries(
-    makeHeaders(noAuth ?? false).entries(),
-  );
-
-  // Merge default headers with custom headers, with custom headers taking precedence
-  const headers = {
-    ...defaultHeaders,
-    ...(options?.headers || {}),
-  };
+  // Use Headers API for better header management
+  const headers = new Headers(makeHeaders(noAuth ?? false));
+  
+  // Merge custom headers
+  if (options?.headers) {
+    const customHeaders = new Headers(options.headers);
+    customHeaders.forEach((value, key) => {
+      headers.set(key, value);
+    });
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Convert Headers object to a plain object
const defaultHeaders = Object.fromEntries(
makeHeaders(noAuth ?? false).entries(),
);
// Merge default headers with custom headers, with custom headers taking precedence
const headers = {
...defaultHeaders,
...(options?.headers || {}),
};
// Use Headers API for better header management
const headers = new Headers(makeHeaders(noAuth ?? false));
// Merge custom headers
if (options?.headers) {
const customHeaders = new Headers(options.headers);
customHeaders.forEach((value, key) => {
headers.set(key, value);
});
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there any performance overhead introduced by using the Headers API compared to a plain object?

Copy link
Contributor

Choose a reason for hiding this comment

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

@srijantrpth, using the Headers API introduces minimal performance overhead compared to using a plain object. The Headers API is optimized for managing HTTP headers efficiently, and it provides benefits like built-in normalization and validation. These features enhance the robustness of header handling without significantly impacting performance. In most cases, the slight overhead is negligible and is outweighed by the advantages in code maintainability and correctness.

If performance is a critical concern, we can consider benchmarking both implementations to measure any differences. However, it's unlikely to be a bottleneck under normal circumstances.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it used across all our environments? If yes, let me rectify it else it's fine

Copy link
Contributor

Choose a reason for hiding this comment

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

@srijantrpth, the Headers API is indeed used in our codebase. Specifically, in src/Utils/request/utils.ts, we create headers using the Headers API:

const headers = new Headers({
  "Content-Type": "application/json",
  Accept: "application/json",
  ...additionalHeaders,
});

Using the Headers API in your implementation would maintain consistency across all our environments. It would be beneficial to adopt it for better header management.

🔗 Analysis chain
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of the Headers API in the codebase
ast-grep --pattern 'new Headers($_)'

Length of output: 324

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, let me rectify the code

Copy link
Contributor

Choose a reason for hiding this comment

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

@srijantrpth, glad to hear you're updating the code! Let me know if you need any assistance.


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Comment on lines 10 to 17
export interface QueryOptions<TBody> {
body?: TBody;
queryParams?: Record<string, any>;
pathParams?: Record<string, any>;
silent?: boolean;
signal?: AbortSignal;
headers?: Record<string, string>; // Add headers support
}
Copy link
Member

Choose a reason for hiding this comment

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

let's not duplicate the type. this is already present in request/types.ts

Comment on lines 25 to 35
// Convert Headers object to a plain object
const defaultHeaders = Object.fromEntries(
makeHeaders(noAuth ?? false).entries(),
);

// Merge default headers with custom headers, with custom headers taking precedence
const headers = {
...defaultHeaders,
...(options?.headers || {}),
};

Copy link
Member

@rithviknishad rithviknishad Dec 16, 2024

Choose a reason for hiding this comment

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

I guess you may be confused about the objective. This would "overwrite" the headers. But the intended behaviour is to "append" the headers while preserving the previously set headers.

Let's stick with using the Headers API. It's there for a purpose :) -- best practices

Refer: https://developer.mozilla.org/en-US/docs/Web/API/Headers/append

image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am sorry about that, I'll fix this and let you know

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

♻️ Duplicate comments (1)
src/Utils/request/query.ts (1)

5-17: ⚠️ Potential issue

Remove duplicate interface definition and use existing QueryOptions from types.ts.

The local QueryOptions interface definition creates unnecessary duplication and reduces type safety. Previous reviews have already addressed this:

  1. The interface already exists in types.ts
  2. The headers property should use HeadersInit type for better Fetch API compatibility

Apply this diff to fix the issues:

 import { Route } from "@/Utils/request/types";
-// Remove conflicting QueryOptions import
+import { QueryOptions } from "@/Utils/request/types";
 import { makeHeaders, makeUrl } from "@/Utils/request/utils";

-// Define QueryOptions locally, including the 'headers' property
-export interface QueryOptions<TBody> {
-  body?: TBody;
-  queryParams?: Record<string, any>;
-  pathParams?: Record<string, any>;
-  silent?: boolean;
-  signal?: AbortSignal;
-  headers?: Record<string, string>; // Add headers support
-}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0f74197 and 596168e.

📒 Files selected for processing (1)
  • src/Utils/request/query.ts (1 hunks)
🔇 Additional comments (1)
src/Utils/request/query.ts (1)

37-40: LGTM! Proper usage of Headers API in fetch options.

The implementation correctly uses the Headers object in the fetch options and properly handles the abort signal.

src/Utils/request/query.ts Outdated Show resolved Hide resolved
@rithviknishad rithviknishad removed question Further information is requested needs-triage labels Dec 16, 2024
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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 596168e and f897a9f.

📒 Files selected for processing (2)
  • src/Utils/request/query.ts (1 hunks)
  • src/Utils/request/utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Utils/request/query.ts
🧰 Additional context used
📓 Learnings (1)
src/Utils/request/utils.ts (1)
Learnt from: rithviknishad
PR: ohcnetwork/care_fe#9458
File: src/Utils/request/utils.ts:61-64
Timestamp: 2024-12-16T13:40:33.928Z
Learning: The application does not use server-side rendering, so directly accessing `localStorage` is acceptable.
🔇 Additional comments (3)
src/Utils/request/utils.ts (3)

53-53: LGTM: Function signature properly updated for custom headers support

The addition of the optional additionalHeaders parameter with HeadersInit type is appropriate for the custom headers requirement.


60-63: LGTM: Token retrieval and authorization header handling

The implementation correctly:

  • Retrieves the token from localStorage (confirmed acceptable as per team's clarification about no SSR)
  • Properly formats and sets the Bearer token

53-63: Verify integration with query functionality

Let's ensure the header changes work correctly with the query implementation.

✅ Verification successful

Based on the results, I can generate the final response as we have clear evidence of the integration:

Header changes are properly integrated with query functionality

The makeHeaders function is correctly used across the request utilities:

  • In query.ts: Used to set headers in query options
  • In request.ts: Applied to request options before fetch
  • No conflicting header manipulations found elsewhere
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of makeHeaders to verify integration
rg -A 3 "makeHeaders\(" --type ts

# Look for any direct Headers manipulation that might conflict
rg -A 3 "new Headers\(" --type ts

Length of output: 1047

src/Utils/request/utils.ts Show resolved Hide resolved
@srijantrpth
Copy link
Contributor Author

@Jacobjeevan Please review the latest changes and let me know if any changes are required.

@Jacobjeevan Jacobjeevan added reviewed reviewed by a core member and removed needs review labels Dec 16, 2024
@rithviknishad rithviknishad merged commit f7b8283 into ohcnetwork:develop Dec 17, 2024
30 checks passed
Copy link

@srijantrpth Your efforts have helped advance digital healthcare and TeleICU systems. 🚀 Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! 🙌

@srijantrpth srijantrpth deleted the issues/9457#/queryRequestmodification branch December 17, 2024 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
reviewed reviewed by a core member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Modify queryRequest to support custom headers
3 participants