This Confluence has been LDAP enabled, if you are an ASF Committer, please use your LDAP Credentials to login. Any problems file an INFRA jira ticket please.

Child pages
  • Making all URLs absolute
Skip to end of metadata
Go to start of metadata

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() );
  • No labels