Policy evaluation
The policy is a list of rules. Each rule has an id, a when condition
written in the rule language, and a then
saying what to do (actions):
rules:
- id: github-reads
when: host under "github.com" and method in [GET, HEAD]
then: allow
- id: no-admin-paths
when: path starts_with "/admin"
then: deny
- id: upload-cap
when: body.bytes > 10mb
then: denyDeny wins
roxy checks every rule against the request. If any matching rule denies, the request is denied. If none denies and at least one allows, it is allowed. If no rule matches, it is denied. The order of the rules makes no difference to the decision.
With the rules above, GET https://github.com/admin matches both
github-reads and no-admin-paths, and is denied.
When rules run
roxy decides whether to forward a request as soon as it has the request head, before any of the body has been sent on. Most rules are decided then.
Some rules read things that are only known later, such as how many body
bytes have been sent (body.bytes) or the response status. roxy checks
these rules again each time the value changes. In the example,
upload-cap is checked as the body streams, and stops the upload once it
passes 10 MiB.
The reference calls the first kind admission rules and the second
in-flight rules. roxy check and roxy rule test say which each rule
is.
A rule checked later can only deny, because by then the request has already gone. It can also log, tag, write state, or change response headers that have not been sent yet. When it denies, roxy stops the exchange: the client gets an error if its response has not started, and otherwise the connection is closed.
A rule that reads the whole body (body.text) is different: roxy holds
the body back until it has read it, and then decides
(body rules).
Effects
Order matters for what rules change, not for the decision. When a
request is allowed, every matching rule's changes apply from top to
bottom, so if two rules set the same header, the lower one wins. The flow
log names the rule that decided as terminal_rule.
A tag set by a rule can only be read by rules below it. roxy rejects a config where a rule reads a tag that a rule further down sets.
When an input is missing
If a rule needs a value roxy cannot get, such as a metric when its table
is full or an address list that failed to load, the request is denied
with 503. roxy never guesses that the condition was false. A value that
is just absent, like a header the client did not send, is null and
compares normally
(missing values).