How it works
fltr is a content-based HTTP request filter. It inspects the Searchable Content of every request, matches it against the Block Rules, and routes the request by its verdict. Matching is binary. The Block Rules have no rank or precedence over each other.
flowchart LR
R(<b>📦 Request</b>) --> BR(<b>📋 Block Rules</b>)
BR -- No Rules match ---> A(<b>✅ Allowed</b>)
BR -- Any Rule matches ---> B(<b>❌ Blocked</b>)
classDef blue fill:#4287ff1F,stroke:#4287ff
classDef green fill:#00c7531F,stroke:#00c753
classDef red fill:#ff1a471F,stroke:#ff1a47
class BR blue
class A green
class B red
Startup
Before fltr starts listening, it:
- Reads the configuration and validates each upstream URL (only
httpandhttpswith a hostname are accepted). - Sends an HTTP
HEADrequest to each configured upstream. Any HTTP response counts as reachable, including error status codes. Network and TLS failures abort the startup. - Loads the Block Rules from
block_rules.json, or the file named byFLTR_BLOCK_RULES_FILE. A Block Rule with no terms, or a blank term after trimming, aborts startup.
Request flow
For each incoming request:
flowchart TD
A(<b>Incoming request</b>)
B(<b>Liveness Endpoint</b><br/>GET / HEAD → 200<br/>Other methods → 405)
A -- Reserved Path /healthz? --> B
A -- Other Request --> C(<b>Read</b><br>Body ≤ <i>FLTR_MAX_BODY_SIZE</i>?)
C -- yes --> D(<b>Assemble</b><br>Searchable Content)
C -- no --> E(<b>Rejected</b><br>413 request too large)
D --> F(<b>Match</b><br>Block Rules)
F -- No Rules match --> G(<b>Allowed</b><br>Forward to Allow Upstream)
F -- Any Rule matches --> H(<i>FLTR_BLOCK_UPSTREAM</i> set?)
H -- yes --> I(<b>Blocked</b><br>Forward to Block Upstream)
H -- no --> J(<b>Discarded</b><br/>200 Request blocked, discarded)
classDef grey fill:#ffffff1F,stroke:#ffffff
classDef red fill:#ff1a471F,stroke:#ff1a47
classDef green fill:#00c7531F,stroke:#00c753
classDef blue fill:#4287ff1F,stroke:#4287ff
class B grey
class C,D,F,H blue
class E,I,J red
class G green
- Health: a request to the Reserved Path
/healthzis answered by fltr itself and never reaches the filter or an upstream.GETandHEADreturn200; any other method returns405. - Read: the body is read up to
FLTR_MAX_BODY_SIZE(default 10 MB). A larger body is rejected with413 request too large. - Assemble: the Searchable Content is built from the request body, the
Title/Messageheaders, and theTitle/titleandMessage/messagequery parameters. Nothing in the URL path is inspected. - Match: fltr checks each Block Rule. A rule matches when every term of that rule is found in the Searchable Content. A request matching any Block Rule is blocked. A request matching none is allowed.
- Route by verdict:
- Allowed: forwarded to the Allow Upstream.
- Blocked: forwarded to the Block Upstream when
FLTR_BLOCK_UPSTREAMis configured. Otherwise discarded, and fltr responds with200 Request blocked, discarded.
See HTTP behavior for a table containing all possible responses.
Forwarding behavior
fltr forwards the method, end-to-end headers, and body, drops the incoming URL path, and combines the upstream's query parameters with the incoming ones. It never adds X-Forwarded-* headers. See HTTP behavior for more detail.
Where each variable fits
FLTR_BLOCK_RULES_FILE: startup (rules loading).FLTR_MAX_BODY_SIZE: step 2 (body reading).FLTR_CASE_SENSITIVE: step 4 (matching).FLTR_ALLOW_UPSTREAMandFLTR_BLOCK_UPSTREAM: step 5 (routing). See Startup for reachability semantics.LOG_LEVELandLOG_FORMAT: logging only; they do not affect filtering or routing.