Skip to content

Conversation

@ravishanigarapu
Copy link
Contributor

@ravishanigarapu ravishanigarapu commented May 22, 2025

πŸ“‹ Description

JIRA ID: AMM-1456

Please provide a summary of the change and the motivation behind it. Include relevant context and details.


βœ… Type of Change

  • 🐞 Bug fix (non-breaking change which resolves an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • πŸ”₯ Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • πŸ›  Refactor (change that is neither a fix nor a new feature)
  • βš™οΈ Config change (configuration file or build script updates)
  • πŸ“š Documentation (updates to docs or readme)
  • πŸ§ͺ Tests (adding new or updating existing tests)
  • 🎨 UI/UX (changes that affect the user interface)
  • πŸš€ Performance (improves performance)
  • 🧹 Chore (miscellaneous changes that don't modify src or test files)

ℹ️ Additional Information

Please describe how the changes were tested, and include any relevant screenshots, logs, or other information that provides additional context.

Summary by CodeRabbit

  • New Features

    • Introduced enhanced handling of user agent information for improved request processing.
    • Added new utilities for managing authorization headers and user agent context.
  • Bug Fixes

    • Improved cookie handling to prevent errors when cookies are missing from requests.
  • Refactor

    • Streamlined feedback and email gateway request processing for greater reliability and maintainability.
    • Centralized and simplified HTTP header and authorization management across services.
  • Chores

    • Improved internal request validation logic for better security and robustness.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 22, 2025

Warning

Rate limit exceeded

@ravishanigarapu has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 27 minutes and 35 seconds before requesting another review.

βŒ› How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 8f52336 and ee5ccb2.

πŸ“’ Files selected for processing (1)
  • src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1 hunks)

Walkthrough

This change introduces new utility classes for handling HTTP request headers, user agent context, and request entity creation. Several service classes are refactored to use these utilities, removing manual header construction and JWT extraction. JWT validation logic is updated to support mobile clients and request wrapping. No public API signatures are changed.

Changes

File(s) Change Summary
src/main/java/com/iemr/helpline104/service/IMRMMR/IMRMMRServiceImpl.java
.../balVivah/BalVivahComplaintImpl.java
.../epidemicOutbreak/EpidemicOutbreakServiceImpl.java
.../feedback/FeedbackServiceImpl.java
.../foodSafetyCopmlaint/FoodSafetyCopmlaintServiceImpl.java
Refactored feedback and email gateway methods to use RestTemplateUtil.createRequestEntity for HTTP entity creation, removing manual JWT and header handling.
src/main/java/com/iemr/helpline104/utils/CookieUtil.java Changed getJwtTokenFromCookie to a static method and added a null check for cookies to prevent null pointer exceptions.
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java Added new utility class RestTemplateUtil with static method createRequestEntity to centralize HTTP entity creation, including propagation of authorization and JWT token headers.
src/main/java/com/iemr/helpline104/utils/UserAgentContext.java Added new utility class UserAgentContext for thread-local storage and retrieval of user agent strings.
src/main/java/com/iemr/helpline104/utils/http/AuthorizationHeaderRequestWrapper.java Added new class to wrap HTTP requests, allowing injection or override of the "Authorization" header.
src/main/java/com/iemr/helpline104/utils/http/HTTPRequestInterceptor.java Modified preHandle to bypass further processing if the "Authorization" header is missing or empty, logging this condition.
src/main/java/com/iemr/helpline104/utils/JwtUserIdValidationFilter.java Refactored JWT validation logic to wrap requests with custom Authorization headers and manage UserAgentContext for mobile clients, adding explicit context management and request wrapping.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant RestTemplateUtil
    participant ExternalAPI

    Client->>Controller: Send HTTP request (with JWT/Authorization)
    Controller->>Service: Call createFeedback (request, feedbackDetails)
    Service->>RestTemplateUtil: createRequestEntity(feedbackDetails, Authorization)
    RestTemplateUtil->>Service: Return HttpEntity with headers
    Service->>ExternalAPI: POST feedback with HttpEntity
    ExternalAPI-->>Service: Response
    Service-->>Controller: Return OutputResponse
    Controller-->>Client: Response
Loading
sequenceDiagram
    participant Client
    participant JwtUserIdValidationFilter
    participant UserAgentContext
    participant FilterChain

    Client->>JwtUserIdValidationFilter: HTTP request
    JwtUserIdValidationFilter->>JwtUserIdValidationFilter: Check JWT in cookie/header
    alt JWT found
        JwtUserIdValidationFilter->>AuthorizationHeaderRequestWrapper: Wrap request with Authorization header
        JwtUserIdValidationFilter->>FilterChain: Continue with wrapped request
    else Mobile client with Authorization
        JwtUserIdValidationFilter->>UserAgentContext: Set user agent
        JwtUserIdValidationFilter->>FilterChain: Continue with request
        JwtUserIdValidationFilter->>UserAgentContext: Clear user agent
    else
        JwtUserIdValidationFilter-->>Client: Respond 401 Unauthorized
    end
Loading

Possibly related PRs

Suggested reviewers

  • drtechie

Poem

In the warren of code, a rabbit hops quick,
Tidying headers, with a utility trick.
JWTs are gathered, user agents in tow,
Through wrappers and filters, requests smoothly flow.
With thread-local carrots and cookies in sight,
This patch brings new orderβ€”oh, what a delight!
πŸ₯•

✨ Finishing Touches
  • πŸ“ Generate Docstrings

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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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
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 (3)
src/main/java/com/iemr/helpline104/service/epidemicOutbreak/EpidemicOutbreakServiceImpl.java (1)

190-198: πŸ› οΈ Refactor suggestion

Consider adding error handling for REST template calls.

While the refactoring to use RestTemplateUtil is good, the method doesn't handle potential RestClientException that could be thrown by RestTemplate.exchange(). Consider adding proper exception handling to ensure errors are properly logged and appropriate responses are returned.

 private OutputResponse createFeedback(String feedbackDetails, HttpServletRequest request) throws IEMRException, JsonMappingException, JsonProcessingException {
 	RestTemplate restTemplate = new RestTemplate();
 	ObjectMapper objectMapper = new ObjectMapper();
 	String url = properties.getPropertyByName("common-url") + "/" + properties.getPropertyByName("create-feedback");
 	HttpEntity<Object> request1 = RestTemplateUtil.createRequestEntity(feedbackDetails, request.getHeader("Authorization"));
-	ResponseEntity<String> responseStr = restTemplate.exchange(url, HttpMethod.POST, request1, String.class);
-	OutputResponse response = objectMapper.readValue(responseStr.getBody(), OutputResponse.class);
-	return response;
+	try {
+		ResponseEntity<String> responseStr = restTemplate.exchange(url, HttpMethod.POST, request1, String.class);
+		OutputResponse response = objectMapper.readValue(responseStr.getBody(), OutputResponse.class);
+		return response;
+	} catch (RestClientException e) {
+		logger.error("Error in feedback creation REST call: " + e.getMessage(), e);
+		throw new IEMRException("Failed to create feedback: " + e.getMessage());
+	}
}
src/main/java/com/iemr/helpline104/service/balVivah/BalVivahComplaintImpl.java (1)

194-203: πŸ› οΈ Refactor suggestion

Consider adding error handling for REST template calls.

While the refactoring to use RestTemplateUtil is good, the method doesn't handle potential RestClientException that could be thrown by RestTemplate.exchange(). Consider adding proper exception handling to ensure errors are properly logged and appropriate responses are returned.

 private OutputResponse createFeedback(String feedbackDetails, HttpServletRequest request) throws IEMRException, JsonMappingException, JsonProcessingException {
 	RestTemplate restTemplate = new RestTemplate();
 	ObjectMapper objectMapper = new ObjectMapper();
 	String url = properties.getPropertyByName("common-url") + "/" + properties.getPropertyByName("create-feedback");
 	HttpEntity<Object> request1 = RestTemplateUtil.createRequestEntity(feedbackDetails, request.getHeader("Authorization"));
-	ResponseEntity<String> responseStr = restTemplate.exchange(url, HttpMethod.POST, request1, String.class);
-	OutputResponse response = objectMapper.readValue(responseStr.getBody(), OutputResponse.class);
-
-	return response;
+	try {
+		ResponseEntity<String> responseStr = restTemplate.exchange(url, HttpMethod.POST, request1, String.class);
+		OutputResponse response = objectMapper.readValue(responseStr.getBody(), OutputResponse.class);
+		return response;
+	} catch (RestClientException e) {
+		logger.error("Error in feedback creation REST call: " + e.getMessage(), e);
+		throw new IEMRException("Failed to create feedback: " + e.getMessage());
+	}
}
src/main/java/com/iemr/helpline104/service/feedback/FeedbackServiceImpl.java (1)

334-342: πŸ› οΈ Refactor suggestion

Create RestTemplate once, and guard against a missing Authorization header

RestTemplate is instantiated on every call to createFeedback, which defeats connection-pooling and makes tuning (timeouts, interceptors, error-handlers, etc.) hard.
In addition, request.getHeader("Authorization") can be null because the filter purposely blanks that header via AuthorizationHeaderRequestWrapper. Passing null to RestTemplateUtil.createRequestEntity results in an Authorization header with an empty value being emitted to the downstream service.

-RestTemplate restTemplate = new RestTemplate();
+// Prefer constructor injection of a singleton bean – shown inline for brevity
+@Autowired
+private RestTemplate restTemplate;
 ...
-HttpEntity<Object> request1 = RestTemplateUtil.createRequestEntity(feedbackDetails, request.getHeader("Authorization"));
+String authHeader = request.getHeader("Authorization");
+HttpEntity<Object> request1 =
+        RestTemplateUtil.createRequestEntity(
+                feedbackDetails,
+                authHeader != null && !authHeader.isBlank() ? authHeader : null);

Consider defining a @Bean RestTemplate with proper timeout settings in a @Configuration class and injecting it wherever needed.
This improves performance, testability, and avoids leaking blank Authorization headers.

🧹 Nitpick comments (2)
src/main/java/com/iemr/helpline104/utils/http/HTTPRequestInterceptor.java (1)

64-67: Added bypass for requests without authorization headers.

The interceptor now allows requests without an authorization header to proceed without validation. While this change supports the new JWT validation approach, consider adding more detailed logging or metrics to monitor such bypassed requests for security auditing.

if (authorization == null || authorization.isEmpty()) {
    logger.info("Authorization header is null or empty. Skipping HTTPRequestInterceptor.");
+   // Consider adding metrics or more detailed logging here
    return true; // Allow the request to proceed without validation
}
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)

32-38: Null User-Agent propagates as literal null

UserAgentContext.getUserAgent() may return null, producing User-Agent: null. Add a guard:

-headers.add(HttpHeaders.USER_AGENT, UserAgentContext.getUserAgent());
+String ua = UserAgentContext.getUserAgent();
+if (ua != null) {
+    headers.add(HttpHeaders.USER_AGENT, ua);
+}
πŸ“œ Review details

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

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 5616c81 and 2d51e89.

πŸ“’ Files selected for processing (11)
  • src/main/java/com/iemr/helpline104/service/IMRMMR/IMRMMRServiceImpl.java (3 hunks)
  • src/main/java/com/iemr/helpline104/service/balVivah/BalVivahComplaintImpl.java (2 hunks)
  • src/main/java/com/iemr/helpline104/service/epidemicOutbreak/EpidemicOutbreakServiceImpl.java (2 hunks)
  • src/main/java/com/iemr/helpline104/service/feedback/FeedbackServiceImpl.java (2 hunks)
  • src/main/java/com/iemr/helpline104/service/foodSafetyCopmlaint/FoodSafetyCopmlaintServiceImpl.java (2 hunks)
  • src/main/java/com/iemr/helpline104/utils/CookieUtil.java (1 hunks)
  • src/main/java/com/iemr/helpline104/utils/JwtUserIdValidationFilter.java (2 hunks)
  • src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1 hunks)
  • src/main/java/com/iemr/helpline104/utils/UserAgentContext.java (1 hunks)
  • src/main/java/com/iemr/helpline104/utils/http/AuthorizationHeaderRequestWrapper.java (1 hunks)
  • src/main/java/com/iemr/helpline104/utils/http/HTTPRequestInterceptor.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/main/java/com/iemr/helpline104/service/balVivah/BalVivahComplaintImpl.java (1)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)
  • RestTemplateUtil (13-42)
src/main/java/com/iemr/helpline104/service/IMRMMR/IMRMMRServiceImpl.java (1)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)
  • RestTemplateUtil (13-42)
src/main/java/com/iemr/helpline104/service/epidemicOutbreak/EpidemicOutbreakServiceImpl.java (1)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)
  • RestTemplateUtil (13-42)
src/main/java/com/iemr/helpline104/service/feedback/FeedbackServiceImpl.java (1)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)
  • RestTemplateUtil (13-42)
src/main/java/com/iemr/helpline104/service/foodSafetyCopmlaint/FoodSafetyCopmlaintServiceImpl.java (1)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)
  • RestTemplateUtil (13-42)
src/main/java/com/iemr/helpline104/utils/JwtUserIdValidationFilter.java (2)
src/main/java/com/iemr/helpline104/utils/http/AuthorizationHeaderRequestWrapper.java (1)
  • AuthorizationHeaderRequestWrapper (10-42)
src/main/java/com/iemr/helpline104/utils/UserAgentContext.java (1)
  • UserAgentContext (3-18)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)
src/main/java/com/iemr/helpline104/utils/UserAgentContext.java (1)
  • UserAgentContext (3-18)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (java)
πŸ”‡ Additional comments (13)
src/main/java/com/iemr/helpline104/utils/UserAgentContext.java (1)

1-18: Good implementation of thread-local storage for user agent information.

This is a well-designed utility class that provides thread-local storage for user agent strings. The implementation follows best practices for thread safety with proper methods for setting, getting, and clearing thread-local data.

src/main/java/com/iemr/helpline104/utils/http/AuthorizationHeaderRequestWrapper.java (1)

10-42: Clean implementation of HttpServletRequestWrapper for Authorization header management.

This is a well-structured wrapper class that follows the standard pattern for HttpServletRequestWrapper implementations. The class correctly overrides all necessary methods to handle the Authorization header consistently, using case-insensitive comparisons and proper collections handling.

src/main/java/com/iemr/helpline104/service/epidemicOutbreak/EpidemicOutbreakServiceImpl.java (2)

60-60: Appropriate import for the new utility class.

Added import for RestTemplateUtil which is used to standardize HTTP request creation.


194-194: Good refactoring to use centralized HTTP entity creation.

The change replaces manual header construction with a call to RestTemplateUtil.createRequestEntity, which centralizes header management logic including authorization, JWT tokens, and user agent propagation. This improves code maintainability and consistency.

src/main/java/com/iemr/helpline104/service/balVivah/BalVivahComplaintImpl.java (2)

63-63: Appropriate import for the new utility class.

Added import for RestTemplateUtil which is used to standardize HTTP request creation.


198-198: Good refactoring to use centralized HTTP entity creation.

The change replaces manual header construction with a call to RestTemplateUtil.createRequestEntity, which centralizes header management logic including authorization, JWT tokens, and user agent propagation. This improves code maintainability and consistency.

src/main/java/com/iemr/helpline104/service/foodSafetyCopmlaint/FoodSafetyCopmlaintServiceImpl.java (2)

55-55: Adding RestTemplateUtil import for centralized HTTP request handling.

This addition supports the refactoring below to use the centralized utility for HTTP request entity creation.


213-216: Improved HTTP request creation with RestTemplateUtil.

The code now uses a centralized utility for creating HTTP request entities instead of manually constructing headers. This improves consistency, ensures proper propagation of authorization headers and JWT tokens, and reduces code duplication across services.

src/main/java/com/iemr/helpline104/utils/CookieUtil.java (1)

27-30: Enhanced JWT token extraction with null safety.

The getJwtTokenFromCookie method has been improved in two ways:

  1. Changed from instance method to static method for easier usage without requiring a CookieUtil instance
  2. Added null check for cookies to prevent NullPointerException when request cookies are null

This makes the method more robust and easier to use from other utility classes like RestTemplateUtil.

src/main/java/com/iemr/helpline104/service/IMRMMR/IMRMMRServiceImpl.java (3)

70-70: Adding RestTemplateUtil import for centralized HTTP request handling.

This addition supports the refactoring below to use the centralized utility for HTTP request entity creation.


202-202: Removed manual header construction code.

The previous code for manually constructing headers has been removed in favor of using the centralized RestTemplateUtil for consistent header management.


283-283: Improved HTTP request creation with RestTemplateUtil.

The code now uses RestTemplateUtil.createRequestEntity to create the HTTP entity with proper headers, including authorization and JWT token. This centralizes header construction logic and ensures consistent propagation of authentication information.

src/main/java/com/iemr/helpline104/utils/JwtUserIdValidationFilter.java (1)

95-103: UserAgentContext is set only for mobile clients but never for web – header may be null

RestTemplateUtil unconditionally adds User-Agent from UserAgentContext.
For non-mobile clients this value is never set, so the outgoing call will contain User-Agent: null.

Either set the context for every request (UserAgentContext.setUserAgent(request.getHeader("User-Agent"))) or let RestTemplateUtil skip the header when the value is null.

Comment on lines 75 to +92
if (jwtFromCookie != null) {
logger.info("Validating JWT token from cookie");
if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromCookie)) {
filterChain.doFilter(servletRequest, servletResponse);
AuthorizationHeaderRequestWrapper authorizationHeaderRequestWrapper = new AuthorizationHeaderRequestWrapper(
request, "");
filterChain.doFilter(authorizationHeaderRequestWrapper, servletResponse);
return;
}
}

if (jwtFromHeader != null) {
} else if (jwtFromHeader != null) {
logger.info("Validating JWT token from header");
if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromHeader)) {
filterChain.doFilter(servletRequest, servletResponse);
AuthorizationHeaderRequestWrapper authorizationHeaderRequestWrapper = new AuthorizationHeaderRequestWrapper(
request, "");
filterChain.doFilter(authorizationHeaderRequestWrapper, servletResponse);
return;
}
} else {
String userAgent = request.getHeader("User-Agent");
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Token-validation flow prevents header-fallback & strips valid Authorization

  1. If a Jwttoken cookie is present but fails validation, the subsequent else if branch is skipped, so a perfectly valid JwtToken header is ignored and the request gets a 401.
  2. When validation succeeds, the request is wrapped with an empty Authorization header. Downstream code (e.g. FeedbackServiceImpl) later forwards that header to other services, so a legitimately authenticated call is propagated as an empty bearer, possibly breaking the chain.
-if (jwtFromCookie != null) {
+if (jwtFromCookie != null && jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromCookie)) {
     ...
-} else if (jwtFromHeader != null) {
+} else if (jwtFromHeader != null && jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromHeader)) {
     ...
-                request, "");
+                request, "Bearer " + (jwtFromHeader != null ? jwtFromHeader : jwtFromCookie));

Refactor the conditional logic to:

  1. Validate cookie token β†’ if valid proceed, else fall through.
  2. Validate header token β†’ if valid proceed.
  3. Otherwise 401.

And instead of blanking the header, propagate the validated bearer token so internal service calls remain authorised.

πŸ“ 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
if (jwtFromCookie != null) {
logger.info("Validating JWT token from cookie");
if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromCookie)) {
filterChain.doFilter(servletRequest, servletResponse);
AuthorizationHeaderRequestWrapper authorizationHeaderRequestWrapper = new AuthorizationHeaderRequestWrapper(
request, "");
filterChain.doFilter(authorizationHeaderRequestWrapper, servletResponse);
return;
}
}
if (jwtFromHeader != null) {
} else if (jwtFromHeader != null) {
logger.info("Validating JWT token from header");
if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromHeader)) {
filterChain.doFilter(servletRequest, servletResponse);
AuthorizationHeaderRequestWrapper authorizationHeaderRequestWrapper = new AuthorizationHeaderRequestWrapper(
request, "");
filterChain.doFilter(authorizationHeaderRequestWrapper, servletResponse);
return;
}
} else {
String userAgent = request.getHeader("User-Agent");
// … lines 1–74 remain unchanged …
// First try a valid cookie, else try a valid header, else 401
- if (jwtFromCookie != null) {
+ if (jwtFromCookie != null && jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromCookie)) {
logger.info("Validating JWT token from cookie");
- if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromCookie)) {
AuthorizationHeaderRequestWrapper authorizationHeaderRequestWrapper = new AuthorizationHeaderRequestWrapper(
- request, "");
+ request, "Bearer " + (jwtFromHeader != null ? jwtFromHeader : jwtFromCookie));
filterChain.doFilter(authorizationHeaderRequestWrapper, servletResponse);
return;
- }
} else if (jwtFromHeader != null) {
+ } else if (jwtFromHeader != null && jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromHeader)) {
logger.info("Validating JWT token from header");
- if (jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtFromHeader)) {
AuthorizationHeaderRequestWrapper authorizationHeaderRequestWrapper = new AuthorizationHeaderRequestWrapper(
- request, "");
+ request, "Bearer " + (jwtFromHeader != null ? jwtFromHeader : jwtFromCookie));
filterChain.doFilter(authorizationHeaderRequestWrapper, servletResponse);
return;
- }
} else {
String userAgent = request.getHeader("User-Agent");
}
// … remainder of method …
πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/helpline104/utils/JwtUserIdValidationFilter.java
between lines 75 and 92, refactor the token validation logic to first validate
the JWT token from the cookie and if it fails, continue to validate the JWT
token from the header instead of skipping it. Only return a 401 if both
validations fail. Additionally, when wrapping the request after successful
validation, ensure the Authorization header is set to the validated token value
instead of an empty string to preserve the authenticated token for downstream
services.

Comment on lines +14 to +22
public static HttpEntity<Object> createRequestEntity(Object body, String authorization) {

ServletRequestAttributes servletRequestAttributes = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
if (servletRequestAttributes == null) {
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8");
headers.add(HttpHeaders.AUTHORIZATION, authorization);
return new HttpEntity<>(body, headers);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid inserting an empty Authorization header

headers.add(HttpHeaders.AUTHORIZATION, authorization); is executed even when authorization is null or blank, resulting in a header like Authorization: being sent.

-headers.add(HttpHeaders.AUTHORIZATION, authorization);
+if (authorization != null && !authorization.isBlank()) {
+    headers.add(HttpHeaders.AUTHORIZATION, authorization);
+}

Apply the same guard in the main path below.

πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java around lines
14 to 22, the code adds the Authorization header without checking if the
authorization string is null or blank, which can lead to sending an empty
Authorization header. Fix this by adding a condition to check if the
authorization string is not null and not blank before adding the Authorization
header. Apply this same check both in the if block shown and in the main path of
the method to prevent empty Authorization headers from being sent.

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 (2)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (2)

18-26: Missing check for null or empty authorization value

The code adds the Authorization header without checking if the authorization parameter is null or empty, which could result in invalid or empty headers being sent.

Apply this guard to prevent adding empty Authorization headers:

-headers.add(HttpHeaders.AUTHORIZATION, authorization);
+if (authorization != null && !authorization.isBlank()) {
+    headers.add(HttpHeaders.AUTHORIZATION, authorization);
+}

36-40: πŸ› οΈ Refactor suggestion

Add null check for authorization and JwtToken headers

Similar to the previous issue, the code adds headers without checking if the values are null or empty, which could result in invalid headers.

headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8");
headers.add(HttpHeaders.USER_AGENT, UserAgentContext.getUserAgent());
-headers.add(HttpHeaders.AUTHORIZATION, authorization);
-headers.add("JwtToken",requestHeader.getHeader("JwtToken"));
+if (authorization != null && !authorization.isBlank()) {
+    headers.add(HttpHeaders.AUTHORIZATION, authorization);
+}
+String jwtToken = requestHeader.getHeader("JwtToken");
+if (jwtToken != null && !jwtToken.isBlank()) {
+    headers.add("JwtToken", jwtToken);
+}
🧹 Nitpick comments (1)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)

15-47: Add method documentation and consider refactoring for better maintainability

This utility method would benefit from proper Javadoc documentation explaining its purpose, parameters, and return value. Additionally, consider breaking it down into smaller methods for better readability and testability.

Consider adding Javadoc and refactoring like this:

/**
 * Creates an HTTP request entity with appropriate headers for REST template calls.
 * 
 * @param body The request body to be included in the entity
 * @param authorization The authorization string to be included in the Authorization header
 * @return An HttpEntity with the provided body and appropriate headers
 */
public static HttpEntity<Object> createRequestEntity(Object body, String authorization) {
    if (isRequestContextAvailable()) {
        return createRequestEntityWithContext(body, authorization);
    } else {
        return createRequestEntityWithoutContext(body, authorization);
    }
}

private static boolean isRequestContextAvailable() {
    return RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes;
}

private static HttpEntity<Object> createRequestEntityWithoutContext(Object body, String authorization) {
    MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
    headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8");
    if (authorization != null && !authorization.isBlank()) {
        headers.add(HttpHeaders.AUTHORIZATION, authorization);
    }
    return new HttpEntity<>(body, headers);
}

private static HttpEntity<Object> createRequestEntityWithContext(Object body, String authorization) {
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
    
    // Add standard headers
    headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8");
    
    // Add user agent if available
    addHeaderIfNotNull(headers, HttpHeaders.USER_AGENT, UserAgentContext.getUserAgent());
    
    // Add authorization if available
    addHeaderIfNotNull(headers, HttpHeaders.AUTHORIZATION, authorization);
    
    // Add JWT token header if available
    addHeaderIfNotNull(headers, "JwtToken", request.getHeader("JwtToken"));
    
    // Add JWT token cookie if available
    addJwtCookie(headers, request);
    
    return new HttpEntity<>(body, headers);
}

private static void addHeaderIfNotNull(MultiValueMap<String, String> headers, String headerName, String headerValue) {
    if (headerValue != null && !headerValue.isBlank()) {
        headers.add(headerName, headerValue);
    }
}

private static void addJwtCookie(MultiValueMap<String, String> headers, HttpServletRequest request) {
    try {
        String jwtTokenFromCookie = CookieUtil.getJwtTokenFromCookie(request);
        if (jwtTokenFromCookie != null) {
            headers.add(HttpHeaders.COOKIE, "Jwttoken=" + jwtTokenFromCookie);
        }
    } catch (Exception e) {
        logger.error("Error while getting jwtToken from Cookie: " + e.getMessage());
    }
}
πŸ“œ Review details

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

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 2d51e89 and 8f52336.

πŸ“’ Files selected for processing (1)
  • src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (1)
src/main/java/com/iemr/helpline104/utils/UserAgentContext.java (1)
  • UserAgentContext (3-18)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (java)
πŸ”‡ Additional comments (2)
src/main/java/com/iemr/helpline104/utils/RestTemplateUtil.java (2)

29-34: Good error handling for JWT token extraction

The try-catch block properly handles exceptions that might occur during JWT token extraction from cookies, which prevents the application from crashing and logs the error for debugging.


41-43: Good check for null JWT token before adding cookie header

The code properly checks if the JWT token is null before adding it as a cookie header, which prevents sending invalid or empty cookies.

@sonarqubecloud
Copy link

@ravishanigarapu ravishanigarapu merged commit 170af88 into PSMRI:develop May 22, 2025
7 of 8 checks passed
srishtigrp78 added a commit to srishtigrp78/Helpline104-API that referenced this pull request May 24, 2025
jwttoken and user-agent validation (PSMRI#50)
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.

2 participants