You can override RequestCycle#newUrlRenderer()
with a different UrlRenderer
to force all links to be absolute.
import org.apache.wicket.request.Request; import org.apache.wicket.request.Url; import org.apache.wicket.request.UrlRenderer; import org.apache.wicket.util.lang.Args; import org.apache.wicket.util.string.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@link UrlRenderer} which generates absolute urls * * @author Bas * */ public class AbsoluteUrlRenderer extends UrlRenderer { private static final Logger log = LoggerFactory.getLogger( AbsoluteUrlRenderer.class ); private final Url contextUrl, filterUrl; public AbsoluteUrlRenderer( Request request, String prefix ) { super( request ); this.contextUrl = buildContextUrl( request, prefix ); this.filterUrl = buildFilterUrl( request, prefix ); log.debug( "Prefix for absolute urls: {}", filterUrl ); } @Override public String renderRelativeUrl( Url url ) { Args.notNull( url, "url" ); if( url.isAbsolute() ) { return url.toString(); } else { Url absolute = fromFilterRelativeToAbsolute( url ); log.debug( "renderRelativeUrl: {} => {}", url, absolute ); String renderedUrl = absolute.toString(); return Strings.isEmpty( renderedUrl ) ? "." : renderedUrl; } } @Override public String renderContextRelativeUrl( String url ) { Args.notNull( url, "url" ); // Prevent prefixing a url twice if( url.startsWith( contextUrl.toString() ) ) { return url; } if( url.startsWith( "/" ) ) { url = url.substring( 1 ); } Url relativeUrl = Url.parse( url ); Url absoluteUrl = fromContextRelativeToAbsolute( relativeUrl ); log.debug( "renderContextRelativeUrl: {} -> {}", relativeUrl, absoluteUrl ); return absoluteUrl.toString(); } private Url buildContextUrl( Request request, String prefix ) { Url url = new Url(); if( prefix != null && prefix.length() > 0 ) { url.getSegments().addAll( Url.parse( prefix ).getSegments() ); } String contextPath = request.getContextPath(); if( contextPath.length() > 0 ) { url.getSegments().addAll( Url.parse( contextPath.substring( 1 ) ).getSegments() ); } if( !url.isAbsolute() ) { url.getSegments().add( 0, "" ); } return url; } private Url buildFilterUrl( Request request, String prefix ) { Url url = buildContextUrl( request, prefix ); String filterPath = request.getFilterPath(); if( filterPath.length() > 0 ) { url.getSegments().addAll( Url.parse( filterPath.substring( 1 ) ).getSegments() ); } return url; } private Url fromContextRelativeToAbsolute( Url url ) { Url absolute = new Url( url ); absolute.prependLeadingSegments( contextUrl.getSegments() ); return absolute; } private Url fromFilterRelativeToAbsolute( Url url ) { Url absolute = new Url( url ); absolute.prependLeadingSegments( filterUrl.getSegments() ); return absolute; } }
There is an optional prefix parameter which you can supply to the constructor to set a fixed prefix. The sole purpose of this prefix is to handle the case where the app server is behind a reverse proxy, and the reverse proxy maps a folder to a root-mapped application. E.g. the reverse proxy maps "/app" to an app running at "/" with the WicketFilter handling "/*". All URLs need to be prefixed with "/app", but AbsoluteUrlRenderer cannot detect this.
Installing this custom UrlRenderer can be done by installing a custom IRequestCycleProvider
:
import org.apache.wicket.IRequestCycleProvider; import org.apache.wicket.request.UrlRenderer; import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.cycle.RequestCycleContext; /** * {@link RequestCycle} provider which overrides the {@link UrlRenderer} to generate absolute links. * * @see {@link AbsoluteUrlRenderer} * @see {@link RequestCycle#getUrlRenderer()} * * @author Bas * */ public class AbsoluteUrlRequestCycleProvider implements IRequestCycleProvider { private final String prefix; public AbsoluteUrlRequestCycleProvider() { this( null ); } public AbsoluteUrlRequestCycleProvider( String prefix ) { this.prefix = prefix; } @Override public RequestCycle get( RequestCycleContext context ) { return new RequestCycle( context ) { @Override protected UrlRenderer newUrlRenderer() { return new AbsoluteUrlRenderer( getRequest(), prefix ); } }; } }
In your Application#init()
method, call
setRequestCycleProvider( new AbsoluteUrlRequestCycleProvider() );