Skip to content

Redirect to the prefered console UI when the server root accessed#4499

Open
madurangasiriwardena wants to merge 1 commit intowso2:4.12.xfrom
madurangasiriwardena:root-path
Open

Redirect to the prefered console UI when the server root accessed#4499
madurangasiriwardena wants to merge 1 commit intowso2:4.12.xfrom
madurangasiriwardena:root-path

Conversation

@madurangasiriwardena
Copy link
Member

@madurangasiriwardena madurangasiriwardena commented Feb 19, 2026

Resolves wso2/product-is#26781

Summary by CodeRabbit

  • New Features
    • Root path requests are now automatically redirected to a configured default user interface context, with intelligent fallback to the standard management interface when no custom context configuration is specified.
    • Supports flexible and configurable routing based on deployment settings, allowing administrators to customize the default landing page destination and improve user navigation efficiency.

@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

Walkthrough

The pull request introduces a new RootRedirectServlet that handles requests to the root path ("/") and redirects to a configured default UI context or falls back to a default management UI path. The servlet is registered with the HTTP Whiteboard in CarbonUIServiceComponent to manage root path requests.

Changes

Cohort / File(s) Summary
New Root Redirect Servlet
core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/RootRedirectServlet.java
New servlet class handling GET/POST requests to root path ("/"). Reads optional default-context from CarbonUIDefinitions; computes redirect URL by replacing Admin Console URL trailing segment or falls back to default management UI path (/carbon/admin/index.jsp). Includes constructor overloads and debug-level logging.
Servlet Registration
core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/internal/CarbonUIServiceComponent.java
Adds import and registration of RootRedirectServlet in the start() method using HTTP Whiteboard pattern, scoped to carbonContext with pattern "/"

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A hop to the root, no more 404 fright,
The redirect now guides visitors right,
To console or context, the path flows with care,
From "/" the servlet knows where to go there! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete, containing only a single issue link without addressing most required template sections. Add comprehensive sections covering Purpose, Goals, Approach, User stories, Release notes, Documentation, Testing, and Security checks as specified in the template.
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a redirect from the server root to the preferred console UI when accessed.
Linked Issues check ✅ Passed The code changes implement the requirement from issue #26781: redirecting requests to the server root (/) to the preferred console UI path.
Out of Scope Changes check ✅ Passed All changes are scoped to addressing the linked issue requirement of implementing root path redirection to the console UI.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment on lines +54 to +56
* @param carbonUIDefinitions the UI definitions containing context configuration
*/
public RootRedirectServlet(CarbonUIDefinitions carbonUIDefinitions) {

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 1

Suggested change
* @param carbonUIDefinitions the UI definitions containing context configuration
*/
public RootRedirectServlet(CarbonUIDefinitions carbonUIDefinitions) {
public RootRedirectServlet(CarbonUIDefinitions carbonUIDefinitions) {
this.carbonUIDefinitions = carbonUIDefinitions;
log.info("RootRedirectServlet initialized with CarbonUIDefinitions");
}

Comment on lines +82 to +83
private void handleRedirect(HttpServletRequest request, HttpServletResponse response)
throws IOException {

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 2

Suggested change
private void handleRedirect(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String redirectUrl = getRedirectUrl(request);
log.info("Redirecting root path request to: " + redirectUrl);

Comment on lines +254 to +258
// Register RootRedirectServlet to handle requests to "/" path
// This is necessary because without a servlet registered for "/", requests to the root path
// would result in a 404 error being forwarded to the error page instead of being handled
// by handleSecurity in CarbonSecuredHttpContext
Servlet rootRedirectServlet = new RootRedirectServlet(carbonUIDefinitions);

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 3

Suggested change
// Register RootRedirectServlet to handle requests to "/" path
// This is necessary because without a servlet registered for "/", requests to the root path
// would result in a 404 error being forwarded to the error page instead of being handled
// by handleSecurity in CarbonSecuredHttpContext
Servlet rootRedirectServlet = new RootRedirectServlet(carbonUIDefinitions);
// Register RootRedirectServlet to handle requests to "/" path
// This is necessary because without a servlet registered for "/", requests to the root path
// would result in a 404 error being forwarded to the error page instead of being handled
// by handleSecurity in CarbonSecuredHttpContext
log.info("Registering RootRedirectServlet for root path handling");
Servlet rootRedirectServlet = new RootRedirectServlet(carbonUIDefinitions);

Copy link

@wso2-engineering wso2-engineering bot left a comment

Choose a reason for hiding this comment

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

AI Agent Log Improvement Checklist

⚠️ Warning: AI-Generated Review Comments

  • The log-related comments and suggestions in this review were generated by an AI tool to assist with identifying potential improvements. Purpose of reviewing the code for log improvements is to improve the troubleshooting capabilities of our products.
  • Please make sure to manually review and validate all suggestions before applying any changes. Not every code suggestion would make sense or add value to our purpose. Therefore, you have the freedom to decide which of the suggestions are helpful.

✅ Before merging this pull request:

  • Review all AI-generated comments for accuracy and relevance.
  • Complete and verify the table below. We need your feedback to measure the accuracy of these suggestions and the value they add. If you are rejecting a certain code suggestion, please mention the reason briefly in the suggestion for us to capture it.
Comment Accepted (Y/N) Reason
#### Log Improvement Suggestion No: 1
#### Log Improvement Suggestion No: 2
#### Log Improvement Suggestion No: 3

@jenkins-is-staging
Copy link

PR builder started
Link: https://github.com/wso2/product-is/actions/runs/22173714253

@jenkins-is-staging
Copy link

PR builder completed
Link: https://github.com/wso2/product-is/actions/runs/22173714253
Status: success

Copy link

@jenkins-is-staging jenkins-is-staging left a comment

Choose a reason for hiding this comment

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

Approving the pull request based on the successful pr build https://github.com/wso2/product-is/actions/runs/22173714253

@pavinduLakshan
Copy link
Member

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 1, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/internal/CarbonUIServiceComponent.java`:
- Around line 257-266: The RootRedirectServlet is registered with the pattern
"/" which acts as a default handler for unmatched paths; update the registration
in CarbonUIServiceComponent or the servlet to ensure only the exact root is
handled: either change the servlet registration pattern passed to
context.registerService(Servlet.class, rootRedirectServlet,
rootRedirectServletProps) from "/" to an empty pattern "" for exact context-root
matching, or add a root-only guard inside RootRedirectServlet (e.g., in
handleRedirect() / doGet()) that checks the request path
(request.getRequestURI() and/or request.getContextPath()) and only performs the
redirect when the path is exactly the context root ("/" or empty), otherwise
respond with 404/chain to next handler.

In
`@core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/RootRedirectServlet.java`:
- Around line 102-104: The code in RootRedirectServlet dereferences
carbonUIDefinitions.getContexts() without checking for null which can cause a
500; update the conditional around carbonUIDefinitions to also check that
carbonUIDefinitions.getContexts() != null before calling containsKey/get, e.g.
guard the expression using carbonUIDefinitions != null &&
carbonUIDefinitions.getContexts() != null &&
carbonUIDefinitions.getContexts().containsKey("default-context") and then set
defaultContext from carbonUIDefinitions.getContexts().get("default-context").

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83139eb and 0c62083.

📒 Files selected for processing (2)
  • core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/RootRedirectServlet.java
  • core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/internal/CarbonUIServiceComponent.java

Comment on lines +257 to +266
// Register RootRedirectServlet to handle requests to "/" path
// This is necessary because without a servlet registered for "/", requests to the root path
// would result in a 404 error being forwarded to the error page instead of being handled
// by handleSecurity in CarbonSecuredHttpContext
Servlet rootRedirectServlet = new RootRedirectServlet(carbonUIDefinitions);
Dictionary<String, String> rootRedirectServletProps = new Hashtable<>();
rootRedirectServletProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/");
rootRedirectServletProps.put("osgi.http.whiteboard.context.select",
"(osgi.http.whiteboard.context.name=carbonContext)");
context.registerService(Servlet.class, rootRedirectServlet, rootRedirectServletProps);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -type f -name "RootRedirectServlet.java"

Repository: wso2/carbon-kernel

Length of output: 232


🏁 Script executed:

fd -type f -name "CarbonUIServiceComponent.java"

Repository: wso2/carbon-kernel

Length of output: 232


🏁 Script executed:

git ls-files | grep -i "root" | head -20

Repository: wso2/carbon-kernel

Length of output: 358


🏁 Script executed:

cat -n "core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/RootRedirectServlet.java"

Repository: wso2/carbon-kernel

Length of output: 5713


🏁 Script executed:

cat -n "core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/internal/CarbonUIServiceComponent.java" | sed -n '250,275p'

Repository: wso2/carbon-kernel

Length of output: 2246


🌐 Web query:

OSGi HTTP Whiteboard servlet pattern "/" exact root match vs default mapping unmatched paths

💡 Result:

In OSGi HTTP Whiteboard, osgi.http.whiteboard.servlet.pattern uses the Servlet URL-pattern rules (Servlet spec §12.2), and the key distinction is:

  • "/" is not an “exact root-only” match. A pattern consisting of only "/" registers the servlet as the default servlet for that ServletContextHelper (context path). It will be selected for any request path that is not matched by a more specific exact/path/extension mapping. (docs.osgi.org)
    Example (context path /app): if no other servlet matches, your "/" servlet can receive /app/foo, /app/foo/bar, etc.

  • "" (empty string) is the exact context root match. The empty-string pattern maps only to the application/context root URL of the form http://host:port/<context-root>/. (docs.osgi.org)
    Example (context path /app): matches /app/ (root), but not /app/foo.

So:

  • If you want a catch-all fallback for otherwise-unmatched paths: use "/".
  • If you want only the context root (/.../): use "".

Citations:


🌐 Web query:

Servlet URL pattern "/" specification exact match or default handler

💡 Result:

In the Servlet spec, a url-pattern of "/" is not an exact match. It designates the application’s default servlet mapping. For this mapping, the container sets:

  • servletPath = requestURI - contextPath
  • pathInfo = null (jakarta.ee)

If you want an exact match for the context root (i.e., only http://host:port/<context-root>/), the spec defines a special pattern: the empty string "". In that case:

  • contextPath = ""
  • servletPath = ""
  • pathInfo = "/" (jakarta.ee)

Related: a pattern ending in "/*" is a path mapping (prefix match), while patterns like "/catalog" are exact matches. (jakarta.ee)

Citations:


"/" servlet pattern registers as default handler for all unmatched paths; add root-only validation.

Pattern "/" in OSGi HTTP Whiteboard is a default servlet mapping—it captures any request not matched by more specific patterns, not just the root URL. Combined with the lack of path validation in RootRedirectServlet.handleRedirect(), unmatched paths will be redirected to the console instead of returning 404.

Either change the pattern to "" (exact context root match per Servlet spec) or add a root-only guard in the servlet. The current implementation doesn't match the stated PR objective to handle root requests only.

Recommended fix: add root path validation
--- a/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/RootRedirectServlet.java
+++ b/core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/RootRedirectServlet.java
@@ -81,6 +81,12 @@ public class RootRedirectServlet extends HttpServlet {
     private void handleRedirect(HttpServletRequest request, HttpServletResponse response) 
             throws IOException {
+        // Only redirect if this is the root path, not other unmatched paths
+        String requestPath = request.getRequestURI().substring(request.getContextPath().length());
+        if (!"/".equals(requestPath)) {
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
         String redirectUrl = getRedirectUrl(request);
         
         if (log.isDebugEnabled()) {

Alternatively, change the servlet pattern from "/" to "" for exact root-only matching.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/internal/CarbonUIServiceComponent.java`
around lines 257 - 266, The RootRedirectServlet is registered with the pattern
"/" which acts as a default handler for unmatched paths; update the registration
in CarbonUIServiceComponent or the servlet to ensure only the exact root is
handled: either change the servlet registration pattern passed to
context.registerService(Servlet.class, rootRedirectServlet,
rootRedirectServletProps) from "/" to an empty pattern "" for exact context-root
matching, or add a root-only guard inside RootRedirectServlet (e.g., in
handleRedirect() / doGet()) that checks the request path
(request.getRequestURI() and/or request.getContextPath()) and only performs the
redirect when the path is exactly the context root ("/" or empty), otherwise
respond with 404/chain to next handler.

Comment on lines +102 to +104
if (carbonUIDefinitions != null &&
carbonUIDefinitions.getContexts().containsKey("default-context")) {
defaultContext = carbonUIDefinitions.getContexts().get("default-context");
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard getContexts() before dereference to avoid 500s on root requests.

Line 103 dereferences carbonUIDefinitions.getContexts() without a null check. If contexts are not initialized, this throws and breaks the root redirect flow.

💡 Proposed fix
-        if (carbonUIDefinitions != null && 
-                carbonUIDefinitions.getContexts().containsKey("default-context")) {
-            defaultContext = carbonUIDefinitions.getContexts().get("default-context");
+        if (carbonUIDefinitions != null
+                && carbonUIDefinitions.getContexts() != null
+                && carbonUIDefinitions.getContexts().containsKey("default-context")) {
+            defaultContext = carbonUIDefinitions.getContexts().get("default-context");
         }
📝 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 (carbonUIDefinitions != null &&
carbonUIDefinitions.getContexts().containsKey("default-context")) {
defaultContext = carbonUIDefinitions.getContexts().get("default-context");
if (carbonUIDefinitions != null
&& carbonUIDefinitions.getContexts() != null
&& carbonUIDefinitions.getContexts().containsKey("default-context")) {
defaultContext = carbonUIDefinitions.getContexts().get("default-context");
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/org.wso2.carbon.ui/src/main/java/org/wso2/carbon/ui/RootRedirectServlet.java`
around lines 102 - 104, The code in RootRedirectServlet dereferences
carbonUIDefinitions.getContexts() without checking for null which can cause a
500; update the conditional around carbonUIDefinitions to also check that
carbonUIDefinitions.getContexts() != null before calling containsKey/get, e.g.
guard the expression using carbonUIDefinitions != null &&
carbonUIDefinitions.getContexts() != null &&
carbonUIDefinitions.getContexts().containsKey("default-context") and then set
defaultContext from carbonUIDefinitions.getContexts().get("default-context").

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.

3 participants