Search code examples
http-redirectprettyfacestrailing-slash

Pretty-Faces redirect loop


hi i'm using pretty faces 3.3.3 in tomcat 7

and this config

<rewrite match="/browse" trailingSlash="append" toCase="lowercase" />
<url-mapping id="browsecategory">
    <pattern value="/browse/" />
    <view-id value="/browser.xhtml" />
</url-mapping>

i want requests without trailing slash after "browse" to be redirected to browse/ (with trailing slash). The background: if the trailing slash is missing, my relative outputLinks are not handeled as subdirectorys, but as files in the current directory.

when i request now

localhost:8081/App/browse 

my browser gets into a redirect loop

EDIT:

is it possible that browse is a reserved keyword? when i replace it with squirrel everything works as expected:

<rewrite match="/squirrel" trailingSlash="append" toCase="lowercase" />
<url-mapping id="browsecategory">
    <pattern value="/squirrel/" />
    <view-id value="/browser.xhtml" />
</url-mapping>

Solution

  • Because of the amount of confusion that has occurred using the <rewrite/> tag in PrettyFaces, we've migrated to a new core architecture for PrettyFaces (//Rewrite 2.0.0.Final) that provides much greater control over application configuration. (Available here http://ocpsoft.org/prettyfaces/)

    I would recommend trying PrettyFaces 4 if your environment permits. You can leave your URL-mappings in the pretty-config.xml file if you wish, but you can now define more custom Rewrite rules, more safely, in a Rewrite ConfigurationProvider:

    <!-- for JSF 2.x -->
    <dependency>
        <groupId>org.ocpsoft.rewrite</groupId>
        <artifactId>rewrite-servlet</artifactId>
        <version>2.0.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.ocpsoft.rewrite</groupId>
        <artifactId>rewrite-config-prettyfaces</artifactId>
        <version>2.0.0.Final</version>
    </dependency>
    

    Leave your pretty-config.xml as it is:

    <url-mapping id="browsecategory">
        <pattern value="/browse/" />
        <view-id value="/browser.xhtml" />
    </url-mapping>
    

    Now also create a ConfigurationProvider to handle your trailing slashes:

    public class RewriteConfig extends HttpConfigurationProvider
    {
       @Override
       public int priority()
       {
         return 10;
       }
    
       @Override
       public Configuration getConfiguration(final ServletContext context)
       {
         return ConfigurationBuilder.begin()
           .addRule()
             .when(Direction.isInbound().and(Path.matches("/{p}")))
             .perform(Redirect.to(context.getContextRoot() + "/{p}/"))
             .where("p").matches("^.*[^/]$");
        }
    }
    

    Don't forget to register/activate the ConfigurationProvider.

    Additionally, you can do your URL-mappings in this configuration file as well, thus removing the need for pretty-config.xml or the PrettyFaces 4 con:

    public class RewriteConfig extends HttpConfigurationProvider
    {
       @Override
       public int priority()
       {
         return 10;
       }
    
       @Override
       public Configuration getConfiguration(final ServletContext context)
       {
         return ConfigurationBuilder.begin()
    
           .addRule(Join.path("/browse/").to("/browser.xhtml"))
    
           .addRule()
             .when(Direction.isInbound().and(Path.matches("/{p}")))
             .perform(Redirect.to(context.getContextRoot() + "/{p}/"))
             .where("p").matches("^.*[^/]$");
        }
    }
    

    I didn't test the regular expression in the matches() clause, but it should be something like that. I hope this helps!