Add feature-flagged behavior to skip URL hydration for non-Page/FileAsset/dotAsset contentlets in Content REST API
@fabrizzio-dotCMS is already working on this.
Since May 5, 2026.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Description
Today the Content REST API hydrates a url value for every contentlet, regardless of its content type. For regular contentlets (anything that is not a Page, FileAsset, or dotAsset) this URL is synthetic — it is built by the fallback path that constructs a URL from the identifier/inode when URL_MAP_FOR_CONTENT is not present. The resulting URL is misleading and rarely useful to API consumers.
Goal: introduce a new behavior that skips URL hydration for regular contentlets in Content REST API responses, gated by a feature flag so the previous behavior can be restored quickly if needed.
Scope
- In scope: Content REST API responses (
/api/v1/content/*, content search endpoints) when serializing contentlets. - Out of scope: GraphQL layer and internal Java APIs — those continue to hydrate URLs as before.
- Always hydrated (unaffected): Page, FileAsset, dotAsset content types — these always have a meaningful URL and must continue to be hydrated.
Behavior
- A feature flag controls the new behavior.
- Default: ON — the new "skip URL hydration for regular contentlets" behavior is active out of the box.
- When OFF, legacy behavior is fully restored for all contentlet types.
- When the flag is ON and a contentlet's base type is not Page, FileAsset, or dotAsset:
- The
urlfield in the REST response is set to an empty string (""). - The identifier/inode-based fallback path that constructs a URL when
URL_MAP_FOR_CONTENTis missing must not run for that contentlet.
- The
- Keep the implementation as simple as possible — minimal new code paths, single guard at the serialization boundary.
Acceptance Criteria
- A feature flag is added (via
Config.getBooleanProperty(...)) that gates the new behavior. Default value is ON. - When the flag is ON and a contentlet's base type is not Page, FileAsset, or dotAsset, the Content REST API returns
url: ""for that contentlet. - When the flag is ON, the identifier/inode-based URL fallback path is bypassed for regular contentlets (no synthetic URL is computed or attached).
- When the flag is ON, Page, FileAsset, and dotAsset contentlets continue to be hydrated with their real URL — unchanged from current behavior.
- When the flag is OFF, all contentlet types — including regular contentlets — receive URL hydration exactly as they did before this change (full backwards compatibility).
- Other layers (GraphQL, internal Java callers) are not modified by this change.
- Unit/integration tests cover all four matrix cases:
- Flag ON + regular contentlet →
url == "", fallback not invoked. - Flag ON + Page/FileAsset/dotAsset → URL hydrated as today.
- Flag OFF + regular contentlet → URL hydrated as today (legacy fallback runs).
- Flag OFF + Page/FileAsset/dotAsset → URL hydrated as today.
- Flag ON + regular contentlet →
Priority
Medium
Additional Context
- Keep the change as small and surgical as possible. The whole point of the feature flag is to make the rollback trivial if the new behavior breaks any consumer.
- The fallback path being bypassed is the one that derives a URL from identifier/inode when
URL_MAP_FOR_CONTENTis not set on the contentlet's content type — that is the URL that this issue considers "synthetic" and not worth shipping for regular contentlets.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.