I am trying to apply multiple dynamic URL rewrite rules sequentially. They each work correctly individually, but with multiple rules enabled, only the last one takes effect.
The first rule matches if:
(http.host eq "en.example.com")
And rewrites the URL path to (the query string is preserved):
The second rule matches if:
any(http.request.uri.args.names[*] == "page")
And rewrites the URL path to (the query string is emptied):
concat(http.request.uri.path, "/", http.request.uri.args["page"])
My expectation was that a URL like
en.example.com/something?page=3 would become
Instead, only the last rule takes effect, and I end up with
en.example.com/something/3 depending on the order of the rules.
As you can see, both rules alter the URL path, referencing
http.request.uri.path. Since, per the documentation, the rules are applied in sequence, and in my testing only the last rule ends up taking effect, this leads me to believe that
http.request.uri.path contains the original request value, even after going through transform rules. Is this indeed the case?
If so, is there any way I can get around this issue, and combine the results of the transformations? Additionally, if this is an intended limitation, what is the intended use-case for sequential transform rules?
Thats correct, the values are immutable for rules in the same phase. i.e. if you rewrite uri.path to ‘a’, it wont be set to ‘a’ until we have evaluated all rules. That means if your first rule rewrites the path to ‘a’, the second rule wont see a URI path of ‘a’. BUT, you can have one rule change the URI Path to ‘a’, and a second rule set the URI Query to ‘b’.
More here: https://developers.cloudflare.com/ruleset-engine/about/rules/#rule-evaluation-and-field-values
Have you looked at consolidating the rules, e.g. to get from
(http.host eq "en.example.com") AND any(http.request.uri.args.names[*] == "page")
Dynamic rewrite of
You could also look at using the
http.request.accepted_languages field to make it even more dynamic, e.g. a dynamic rewrite rule of:
Would rewrite to
/en-GB/something/3 for me, or potentially
/de/something/3 for a visitor with a browser language of German, etc.
Thanks for the clarification, and for the documentation link. I had missed that part of the docs.
Yeah, I did consider joining my rules together as a workaround, though my example here was a bit simplified. In my actual scenario, I’ll need several more rules to account for all combinations of matches. In any case, my question has been answered.
I’ll just leave here the feedback that it would be extremely useful to have access to the transformed URI within the rules. It would greatly increase the flexibility of the (already very useful) Transform Rules system, and make it incredibly powerful. To maintain backwards compatibility, this functionality could be implemented with a new set of fields, say
transformed.http.request.uri.*, similarly to how
raw.http.request.uri.* currently represents another variant of
Thanks again for the reply, and the tips. Let me add that the Transform Rules system is extremely useful and highly appreciated, and I hope to see it becoming even more powerful in the future.
This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.