I assume you're using Core Components Page component.
It looks like you're running into:
https://github.com/adobe/aem-core-wcm-components/blob/master/bundles/core/src/main/java/com/adobe/cq...
...based on the above code, you could add a vanity URL to the target page that is the page URLe with minus the ".html" and it looks like that should work.
If you wanted to write come code, you could overlay the Core Components Page's "redirect.html" script, and provide your own redirect target resolution, for example:
(This may need some syntax correction/tweaks - I wrote it in the forum post so its not exact but should give you the idea :))
Overlay: /apps/..../components/my-page/redirect.html
<template data-sly-template.redirect="${ @ redirectTarget}">
<p
data-sly-use.myCustomRedirect="com.example.blah.MyCustomRedirect.class @ redirectTargetPage = redirectTarget.page">
class="cmp-page__redirect">${'This page redirects to' @ i18n}
<a href="${myCustomRedirect.getURL}">${redirectTarget.page.title || myCustomRedirect.getURL}</a>
</p>
</template>
com.example.blah.impl.MyCustomRedirectImpl.java (and make corresponding SlingModel interface MyCustomRedirect.java)
@Model(adaptables = SlingHttpServletRequest.class, adapters = {MyCustomRedirect.class})
public class MyCustomRedirectImpl implements MyCustomRedirect {
@RequestAttribute // I think this is right injector for the params passed in from HTL... if not, you can use the catchall @inject (but better to figure out the right injector)
private com.adobe.cq.wcm.core.components.models.Page redirectTargetPage;
@Override
public String getURL() {
NavigationItem navigationItem = redirectTargetPage.getRedirectTarget();
if ( /** logic to determine if .html should be removed from redirect ** /) {
return StringUtils.removeEnd(navigationItem.getUrl(), ".html"));
} else {
return navigationItem.getUrl();
}
}
}