Routing and mirroring
On http ports a rule can send matching requests to a different service instead, or send a copy of them somewhere and compare the two answers. Both are for the moment you have a fix for one endpoint and do not want to redeploy, or trust, the whole service yet.
route
- name: patched admin
match: { path: '^/admin', method: 'GET|POST' }
route: 19681 # host:port, or a bare port for something on this machineMatching requests go to the patched copy; everything else carries on to the service untouched. The patched copy can be anything that speaks http: a container, a script, a second instance of the service with one handler changed.
mirror
- name: rewrite under test
match: { path: '^/api/' }
mirror: 19682The client always gets the real service's answer. The copy goes out alongside, so a mirror that is slow, broken or missing costs the client nothing.
Status and body are compared, and a difference is logged as a warning naming the request and where the answers diverge. Headers are not compared, since dates and the like differ on every request. Matching answers are logged at debug. vulnboxd_mirror_total counts each outcome: agrees, body differs, status differs or unreachable.
A request that is routed and mirrored compares the copy against whatever actually served it.
Limitations
- Both are settled from the head, before the body is read, so they can only use head conditions:
method,path,headersandheaders_opt, plusnot. - A rule either redirects or edits: a
routeormirrorrule cannot have anactionor change the message. Put blocks and rewrites in rules of their own; they still apply to routed requests. - A rule either routes or mirrors. To do both, use two rules.
- They only apply to requests, so
dirmust bein, the default. - If several rules match, the first
routeand the firstmirrorwin. - Mirroring holds the request and the answer in memory to replay and compare them, so keep it on routes whose messages fit
limits.buffered_body. A larger answer is refused while a mirror is on it.