how to stop processing other rules if one is found

Splash Forums Rewrite Users how to stop processing other rules if one is found

This topic contains 14 replies, has 3 voices, and was last updated by  Serkan Durusoy 5 years, 6 months ago.

Viewing 15 posts - 1 through 15 (of 15 total)
  • Author
    Posts
  • #18221

    Serkan Durusoy
    Participant

    Hi Everyone,

    I’m trying to create a rewrite configuration where:

    1) if inbound url is http://localhost/sitemap.xml FORWARD to http://localhost/fi/sitemap

    2) if not, REDIRECT all http://localhost/xxx TO http://localhost/fi/xxx

    Below is my config:

    ===============================================

    package com.dna.bifincan.root.urlrewrite;

    import com.ocpsoft.rewrite.config.Configuration;

    import com.ocpsoft.rewrite.config.ConfigurationBuilder;

    import com.ocpsoft.rewrite.config.Direction;

    import com.ocpsoft.rewrite.servlet.config.HttpConfigurationProvider;

    import com.ocpsoft.rewrite.servlet.config.Path;

    import com.ocpsoft.rewrite.servlet.config.Redirect;

    import com.ocpsoft.rewrite.servlet.config.rule.Join;

    import javax.servlet.ServletContext;

    public class BifincanConfigurationProvider10 extends HttpConfigurationProvider {

    @Override

    public int priority() {

    return 10;

    }

    @Override

    public Configuration getConfiguration(final ServletContext context) {

    return ConfigurationBuilder.begin()

    .addRule(Join.path("/sitemap.xml").to("/fi/sitemap"))

    .defineRule()

    .when(Direction.isInbound()

    .and(Path.matches("{path}")

    .where("path").matches(".*"))

    .andNot(Path.matches("{path}")

    .where("path").matches("(sitemap|sitemap\.xml)"))

    )

    .perform(Redirect.permanent("/fi{path}"));

    }

    }

    ===============================================

    for this I tried the andNot but it seems not to work. Perhaps there is something very trivial I’m missing here.

    Apart from that, I’m actually wondering if there is a “stop processing all other rules” option once we hit one rule.

    #22280

    Serkan Durusoy
    Participant

    Oh by the way I always thought the PRIORITY can be used for this purpose, but apparently not.

    For example, it would be great if I had a priority 0 (or anything smaller than 10) config with

    .addRule(Join.path(“/sitemap.xml”).to(“/fi/sitemap”))

    .stop; << notice the stop processing more rules ;)

    #22281

    Hey there,

    I just did a quick test for this usecase. I think the problem is that the forwarded request of the first rule also matches the second rule. IMHO you can fix this by adding a DispatchType.isRequest() condition to both rules (especially the second one which matches the forwarded request).

    Something like this

    return ConfigurationBuilder.begin()
    .defineRule()
    .when(Direction.isInbound().and(DispatchType.isRequest()).and(Path.matches("/sitemap.xml")))
    .perform(Forward.to("/fi/sitemap"))
    .defineRule()
    .when(Direction.isInbound().and(DispatchType.isRequest()).and(Path.matches("{path}").where("path").matches(".*")))
    .perform(Redirect.permanent("/fi{path}"));

    Does this work for you?

    Christian

    #22282

    Christian, you beat me to it. Thats what I would recommend. We should probably add a “Stop()” operation. Note that Redirect() implicitly calls stop, but Forward() does not.

    #22283

    Hmmm. I have .handled() and .abort() working, but .proceed() is a bit strange and I may have to remove it since there is currently no way to do that. I may add .disable() however, which would disable all Rewrite functionality on an entire request (both inbound and outbound rewriting.)

    I think that’s a more useful feature than being able mark a request as HANDLED and continue processing. But in the end, will probably need both.

    #22284

    Serkan Durusoy
    Participant

    Hi Christian & Lincoln,

    I tried Christian’s suggestion, but strange enough, I got 404 when I accessed http://localhost/sitemap.xml

    any other path translates to /fi/path without problem.

    #22285

    Serkan Durusoy
    Participant

    Hi Lincoln,

    I have a suggestion (I hope it makes sense)

    Since we have “priorities”, why not keep them completely separate and depending on the priority, once one config is processed, do not continue on to the other configuration providers.

    If one needs to combine multiple rules, it can be done within a single configuration provider.

    If we need completely separate rulesets, having multiple configuration providers with different priorities would then make better sence (imho).

    or perhaps instead of having one public Configuration getConfiguration(final ServletContext context) in a configuration provider, we can have multiple configurations as well as a configurationAssembler that can decide what to do while processing individual configurations.

    Having written all this, a configurationAssembler actually begins to make more sense to me.

    #22286

    The problem with priorities overriding other configurations is when you have an operation that needs to perform some type of action that does *not* abort the request, or mark it as handled – e.g: when you want to add a header, or a request parameter value. So we can’t do that, but I think that providing a lifecycle control is reasonable.

    I think the best solution is to properly engineer your rules so that they do not conflict.

    Regarding your 404 errors – Is it possible that you have nothing to handle that address?

    Also, this rule looks cyclic to me. It will generate a URL that also matches the rule, leading probably to an infinite loop.

    .defineRule()
    .when(Direction.isInbound().and(DispatchType.isRequest())
    .and(Path.matches("{path}").where("path").matches(".*")))
    .perform(Redirect.permanent("/fi{path}"));

    You might want to add a constraint to this pattern, so that you can ignore anything that already starts with “/li”.

    .defineRule()
    .when(Direction.isInbound().and(DispatchType.isRequest())
    .and(Path.matches("{path}").where("path")
    .matches(".*").constrainedBy(new Constraint() {...})))
    .perform(Redirect.permanent("/fi{path}"));

    #22287

    Serkan Durusoy
    Participant

    Hi Lincoln,

    “but I think that providing a lifecycle control is reasonable”

    I hope you put this in your development plan. The only problem I see in engineering proper rules is that the use of nested .when.and.this.that followed by other .definerule.this.that.oh.my.god can make it hard to pinpoint problems. Having the ability to separate rulesets and define the relationship between these separate sets just sounds like an encouragement to me.

    Regarding your questions:

    1) If I directly enter http://localhost/fi/sitemap, I get valid response, even http://localhost/sitemap works (redirects to /fi/sitemap) but somehow /sitemap.xml returns 404 response

    2) You are right to be alerted there, that was my initial concern also, but it turns out, Tomcat does that for you. If there are /path1 /path2 /path3 applications already deployed in the same virtual host, requests to their uri’s take precedence and / is not invoked.

    #22288

    @Serkan:

    Perhaps the first rule doesn’t work because Tomcat keeps a forwarded request within the same webapp (ROOT.war in this case) and doesn’t delegate to another application with a completely different context path (/fi in your case). IMHO this would even make sense. You could try this by temporarily changing the forward to a redirect in the first rule.

    Christian

    #22289

    Serkan Durusoy
    Participant

    Hi Christian,

    It appears you are correct.

    I removed the config, and will make peace with it.

    #22290

    Oh! Of course! No, you cannot forward to another Servlet Context, that’s part of the specification. I wish I’d seen that sooner! Glad you got it working.

    #22291

    Serkan Durusoy
    Participant

    The only viable solution would be to put apache or some other web server in front of the app, but the gain is less than the cost of managing a second server.

    Instead, I’ll point google to the correct location of sitemap.xml in webmaster tools.

    For general redirect from {ROOT}/somepath to {MYAPP}/somepath, ocpsoft rewrite saves the day and saves me from having to manage a web server.

    note: I know I could have changed the context of my app to root, but I don’t want to do that for various reasons.

    #22292

    BTW. The Lifecycle.*() control has been implemented and is part of 1.0.1.Final and up :)

    #22293

    Serkan Durusoy
    Participant

    kudos!

Viewing 15 posts - 1 through 15 (of 15 total)

You must be logged in to reply to this topic.

Comments are closed.