import_headers takes an array of per-spec option tables, each describing how a single header name or pattern should be imported into the message metadata. Compared to import_x_headers it adds: * Trailing-`*` wildcard patterns (e.g. `X-*`) alongside exact names. Bare/leading/interior wildcards are rejected at compile time. * `match` of `first`, `last` (default), or `all`. `all` captures every matching header instance as an array of strings; the others capture a string. Specs that produce no matches write nothing. * `transform` selects the metadata key style: `snake_case` (default, matches the existing import_x_headers behavior), `kebab_case`, `camel_case`, or `pascal_case`. Header matching itself is always case-insensitive. * `target` overrides the metadata key for exact-name specs. * `remove` strips the matched headers from the message body in a single follow-up pass. When more than one spec could match a header, the first matching spec wins, so callers can place specific rules ahead of a wildcard catch-all. import_x_headers now delegates to import_headers, so its behavior is unchanged and the two share a single implementation. retain_headers now passes the header index alongside the &Header to its closure, which import_headers uses for its post-pass removal step instead of tracking a parallel counter. Existing callers that don't need the index ignore it with `_`. Closes: #515
3.4 KiB
tags
| tags | |
|---|---|
|
import_headers
message:import_headers(SPECS)
{{since('dev')}}
Iterates the headers of the message, importing matching header values into the
message metadata. SPECS is an array of tables, one per header name or pattern,
each describing how that header should be matched, named in the metadata, and
optionally removed.
This is a more flexible alternative to message:import_x_headers. The same call can be used to import multiple distinct headers with different rules, and can also be used to strip the matched headers from the message body in a single pass.
Spec fields
Each entry in SPECS accepts the following fields:
-
name(required, string) — the header name to match.Matching is always case-insensitive. The pattern can be either a precise header name (e.g.
"Subject") or a name with a single trailing*wildcard (e.g."X-*"), which matches any header whose name begins with the literal portion of the pattern. Bare*, leading wildcards, and interior wildcards are not supported. -
match(optional, string, default"last") — which matching headers to capture:"first"— capture the first matching header value as a string."last"— capture the last matching header value as a string."all"— capture every matching header value as an array of strings.
-
transform(optional, string, default"snake_case") — how to derive the metadata key from the matched header name. All transforms produce a deterministic key. Examples below assume a matched header namedX-Campaign-Id:"snake_case"—x_campaign_id(matches the transform performed by message:import_x_headers)"kebab_case"—x-campaign-id"camel_case"—xCampaignId"pascal_case"—XCampaignId
-
target(optional, string) — explicitly set the metadata key to use, bypassingtransform. Only valid whennameis a precise header name; usingtargetwith a wildcard pattern produces an error. -
remove(optional, bool, defaultfalse) — whentrue, the matched header instances are removed from the message body after their values have been captured.
If a spec produces no matches, no metadata is written for it (including for
match = "all", which writes nothing rather than an empty array).
When more than one spec could match a header, the first spec in SPECS that
matches wins. This lets you place a precise rule for a specific header in
front of a broader wildcard catch-all.
Examples
Import all X- headers into metadata, and strip them from the message:
msg:import_headers {
{ name = "X-*", remove = true },
}
Capture every Received: header as an array, while also lifting the subject:
msg:import_headers {
{ name = "Received", match = "all" },
{ name = "Subject" },
}
Treat one specific header specially, while still importing the rest of the
X- headers with the default transform:
msg:import_headers {
{ name = "X-Campaign-Id", target = "campaign_id" },
{ name = "X-*" },
}
Use a different naming style:
msg:import_headers {
{ name = "X-*", transform = "camel_case" },
}
-- X-Campaign-Id is captured as `xCampaignId`