Skip to content

Make UI REST context path dynamic via server-injected window.__openidm_context_path#154

Merged
vharseko merged 3 commits intocopilot/make-rest-context-path-configurablefrom
copilot/fix-ui-context-path-issue
Apr 9, 2026
Merged

Make UI REST context path dynamic via server-injected window.__openidm_context_path#154
vharseko merged 3 commits intocopilot/make-rest-context-path-configurablefrom
copilot/fix-ui-context-path-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 9, 2026

Constants.js hardcoded context = "openidm", breaking the entire UI when the server runs with a custom REST context path (e.g. -Dopenidm.context.path=/myidm). All UI API calls would 404, causing 18 Playwright smoke test failures.

Changes

  • ResourceServlet.java — new handleIndexHtml() intercepts index.html serving and injects an inline script before </head> with the runtime-configured context path. Escapes <, >, &, ", ' to prevent XSS. Uses replaceFirst() to be safe with malformed HTML:

    <script>window.__openidm_context_path="myidm";</script>
    </head>
  • Constants.js — reads the injected global with fallback to "openidm" for backward compatibility with older backends:

    commonConstants.context = (typeof window !== "undefined" && window.__openidm_context_path)
        ? window.__openidm_context_path
        : "openidm";
  • openidm-ui-api/index.html — Swagger UI default URL now uses window.__openidm_context_path instead of hardcoded /openidm/?_api.

  • ConstantsTest.js — adds QUnit tests for the window.__openidm_context_path override and fallback behaviour.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • central.sonatype.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.14/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.14/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.14 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.14/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/OpenIDM/OpenIDM org.codehaus.plexus.classworlds.launcher.Launcher compile -pl openidm-servlet -am -q (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.14/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.14/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.14 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.14/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/OpenIDM/OpenIDM org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)
  • maven.alfresco.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.14/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.14/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.14 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.14/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/OpenIDM/OpenIDM org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)
  • repository.jboss.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.14/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.14/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.14 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.14/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/OpenIDM/OpenIDM org.codehaus.plexus.classworlds.launcher.Launcher compile -pl openidm-servlet -am -q (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.14/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.14/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.14 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.14/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/OpenIDM/OpenIDM org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)
  • www.eclipse.org
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/tools/linux64/java/bin/java /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/tools/linux64/java/bin/java -jar /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/xml/tools/xml-extractor.jar --fileList=/tmp/codeql-scratch-dd852eba2a5d9229/dbs/java/working/files-to-index10374774516808572425.list --sourceArchiveDir=/tmp/codeql-scratch-dd852eba2a5d9229/dbs/java/src --outputDir=/tmp/codeql-scratch-dd852eba2a5d9229/dbs/java/trap/java (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Problem

PR #142 made the REST context path configurable via -Dopenidm.context.path=/myidm, but the UI JavaScript still hardcodes commonConstants.context = "openidm" in Constants.js. When the server runs with a custom context path like /myidm, the UI sends all REST requests to /openidm/* which no longer exists, causing the entire UI to fail to load. This breaks all Playwright smoke tests (18 failures) when OPENIDM_CONTEXT_PATH=/myidm.

Root Cause

Constants.js at openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/util/Constants.js line 20:

commonConstants.context = "openidm";

This value is used by all UI delegates to construct REST API URLs like "/" + Constants.context + "/info/login". When the backend is at /myidm, these requests 404.

Additionally, there are a few places in the UI JS that hardcode "/openidm" directly instead of using Constants.context.

Required Changes

1. ResourceServlet.java — inject context path into index.html

File: openidm-servlet/src/main/java/org/forgerock/openidm/ui/internal/service/ResourceServlet.java

When serving index.html (the entry point for both Admin and Enduser UIs), inject a small inline <script> tag before </head> that sets window.__openidm_context_path to the configured context path value (without leading slash). The value comes from System.getProperty(ServerConstants.OPENIDM_CONTEXT_PATH_PROPERTY, ServerConstants.OPENIDM_CONTEXT_PATH_DEFAULT).

The injection should look like:

<script>window.__openidm_context_path="myidm";</script>
</head>

The existing index.html handling already sets Cache-Control: no-cache for this file (line 133). Replace the normal handle() call for index.html with a new method that:

  1. Reads the file into a String
  2. Computes the context value (strip leading / since Constants.context doesn't use it)
  3. Replaces </head> with the injection + </head>
  4. Writes the modified HTML to the response

Import ServerConstants from org.forgerock.openidm.core.ServerConstants (the openidm-system dependency is already available to this module).

2. Constants.js — read injected value

File: openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/util/Constants.js

Change line 20 from:

commonConstants.context = "openidm";

to:

commonConstants.context = (typeof window !== "undefined" && window.__openidm_context_path)
    ? window.__openidm_context_path
    : "openidm";

This preserves backward compatibility — if the variable is not injected (e.g., running with an older backend), it falls back to "openidm".

3. API Explorer index.html — fix hardcoded /openidm/?_api

File: openidm-ui/openidm-ui-api/src/main/resources/index.html

Change the default Swagger JSON URL from:

url = "/openidm/?_api";

to:

var ctx = (window.__openidm_context_path || "openidm");
url = "/" + ctx + "/?_api";

4. Fix remaining hardcoded "/openidm" in JS delegates

These files use "/openidm" directly instead of going through Constants.context. Fix them:

  • openidm-ui/openidm-ui-common/src/main/js/org/forgerock/openidm/ui/common/delegates/ResourceDelegate.js — in the linkedView function, change:

    serviceUrl: constants.host + "/openidm/endpoint/linkedView/" + resourcePath,

    to:

    serviceUrl: constants.host + "/" + constants.context + "/endpoint/linkedView/" + resourcePath,
  • openidm-ui/openidm-ui-admin/src/main/js/org/forgerock/openidm/ui/admin/mapping/util/MappingUtils.js — in deleteMappingChildren, change:

    "serviceUrl": "/openidm/repo/links",

    to:

    "serviceUrl": "/" + constants.context + "/repo/links",

    (Make sure constants is available in scope — it's already imported as a dependency in this file's define() block.)

  • openidm-ui/openidm-ui-admin/src/main/js/config/validators/AdminValidators.js — find the validation check v === "/openidm" and change it to use Constants.context:

    v === "/" + Constants.context

    (Make sure Constants is in scope — check the define() imports.)

5. Update ConstantsTest.js

File: openidm-ui/openidm-ui-common/src/test/qunit/tests/org/forgerock/openidm/ui/common/util/ConstantsTest.js

Add a test that verifies the context can be overridden via window.__openidm_context_path. The test should:

  1. Save original value
  2. Set window.__openidm_context_path = "myidm"
  3. Verify that re-requiring Constants picks up the override (or at least verify the fallback logic)
  4. Restore original value

6. No changes needed to e2e/ui-smoke-test.spec.mjs

The Playwright tests should pass as-is because the UI will now dynamically pick up the correct context path from the injected window.__openidm_context_path.

Important Notes

  • ServerConstants.OPENIDM_CONTEXT_PATH_PROPERTY and ServerConstants.OPENIDM_CONTEXT_PATH_DEFAULT already exist on the PR bran...

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Fix hardcoded UI context path for REST requests Make UI REST context path dynamic via server-injected window.__openidm_context_path Apr 9, 2026
Copilot AI requested a review from vharseko April 9, 2026 15:17
@vharseko vharseko marked this pull request as ready for review April 9, 2026 16:48
@vharseko vharseko merged commit ee9dc32 into copilot/make-rest-context-path-configurable Apr 9, 2026
14 checks passed
@vharseko vharseko deleted the copilot/fix-ui-context-path-issue branch April 9, 2026 16:48
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