uri-blocker
Blocks requests whose request URI matches any configured block_rules regex. Matching requests receive a configurable status (default 403) through the node's denied port. Place it at the front of the pipeline, before auth and upstream nodes.
Configuration
block_rules is required and must be non-empty; regexes are compiled at config load, so an invalid pattern fails fast.
| Key | Type | Default | Description |
|---|---|---|---|
block_rules | array of regex strings | required | Rules tested against the request URI. A request matching any rule is rejected. |
rejected_code | integer (200–599) | 403 | HTTP status for rejections. |
rejected_msg | string | — | When set, rejections carry a JSON body {"error_msg": ...}; when unset the body is empty. |
case_insensitive | bool | false | Match rules case-insensitively (each rule is compiled with (?i)). |
type: uri-blocker
config:
block_rules: ["root.exe", "root.m+", "^/admin/"]
rejected_code: 404
case_insensitive: true
Matching
The subject is the request path plus ?query when query parameters exist, so a rule can hit either the path (^/admin/) or a query value (root.exe against /download?file=root.exe). Matching is unanchored Rust regex syntax; anchor with ^/$ where needed.
Behavior
A blocked request writes rejected_code onto context.response — with a JSON body {"error_msg": rejected_msg} (content-type: application/json) when rejected_msg is set, otherwise an empty body — and exits through the denied port. Non-matching requests pass through the success port untouched; the plugin does not write to context.message.
featherbit compiles each rule separately and tests them in order, giving clear per-rule config errors. The query string is rebuilt from parsed parameters (sorted key=value pairs) rather than the raw wire bytes, and patterns use Rust regex syntax, not PCRE.
Ports
uri-blocker declares three output ports: success, denied (a rejection is prepared), and error (never actually used — the plugin never fails). Like success, denied is a mandatory port: the policy compiler rejects any policy that leaves it unwired. Wire uri-blocker.denied straight to client so the prepared rejection reaches the caller instead of continuing into upstream:
edges:
- from: uri-blocker.success
to: upstream.in
- from: uri-blocker.denied
to: client.in
Errors
This node never fails at execution time: it always returns through success, so its error port is never taken.