Class GuardRuleParser

java.lang.Object
org.frontcache.guard.GuardRuleParser

public class GuardRuleParser extends Object
Parses one line of guard-rules.conf into a GuardRule. Line format (see docs/frontcache-protection-tech-design.md): <name> | <predicate> ; <predicate> ... | <action> [| dry-run] A rate: predicate is moved to the END of its condition here (see parseCondition(String, String)); a rule may hold at most one. Actions: allow reject:<status> [body] redirect:<301|302|303|307|308> <target> Every rejection is reported as a GuardConfigException so the caller can skip that single line and keep the rest of the file working.
  • Constructor Details

    • GuardRuleParser

      public GuardRuleParser(Set<String> allowedRedirectHosts)
      Parameters:
      allowedRedirectHosts - hosts an absolute redirect target may point at. Relative targets are always allowed; anything else is refused at load time, so a stray config line cannot point the whole site at another host.
  • Method Details

    • parse

      public GuardRule parse(String line)
    • splitFields

      public static List<String> splitFields(String line)
      Splits a rule line into its name | condition | action [| flag] fields. Public because bots.conf uses the same line format and must split it the same way - see BotRuleParser. One splitter, so the alternation bug below cannot be re-introduced in the second file. The obvious line.split("\\|") is wrong, and was: | is also regex alternation, so a perfectly ordinary predicate like uri~^/(recent|user)-contributions\.htm got shredded at the alternation and the rule was refused at load time as "invalid regex ... Unclosed group". The rest of the file kept working, which is what made it invisible: on a production node this silently disabled 5 of 19 rules - and they were every anti-scraper redirect, i.e. exactly the rules whose absence costs nothing until a flood arrives. So a | separates fields only where a regex cannot be using it: outside any (...) group, outside any [...] character class, and not backslash-escaped. Fields come back byte-identical - nothing is unescaped - so \| still reads as a literal pipe to the regex engine, and a top-level alternation is written the way it already was, in parentheses.