# XML reference: ingesting, filtering, scripting, pruning, and forwarding an# XML webhook. Every node here works on the XML DOM rather than on JSON.## Requires XML_SOURCE_SECRET (the HMAC secret of the sending system) and# XML_UPSTREAM_URL (where the pruned document is forwarded).## The HMAC is verified against the raw bytes before anything parses them (I6),# so a malformed or unsigned document never reaches the XML parser.server: addr: ":8080" max_body_bytes: 1048576flows: xml_intake: nodes: - {id: in, type: http_trigger, description: "Where the source system posts its XML document.", path: /webhooks/xml, methods: [POST]} - {id: body, type: read_body, description: "Buffers the raw bytes so the signature can be verified.", max_bytes: 1048576} - {id: auth, type: auth, description: "Verifies the sending system's HMAC over the raw bytes.", scheme: hmac_sha256_hex, secret: "${XML_SOURCE_SECRET}", signature_header: X-Hub-Signature-256} - {id: env, type: envelope, description: "Parses the document into an XML DOM.", body_format: xml} # Filter paths address elements below the root by local name, and an # attribute with a leading @. Namespace prefixes are ignored. - {id: only_orders, type: filter, description: "Continues only for documents carrying an ORDER with an amount.", on_no_match: drop, conditions: [{source: body, path: ORDER.Amount, operator: exists}]} # The script sees the DOM as a tagged node tree: {name, ns, attr, attrns, # text, children}. It must return the same shape. - id: tag type: code description: "Reads the order amount off the DOM into a variable for routing." timeout: 50ms script: | const order = input.body.root.children.find(function (c) { return c.name === 'ORDER'; }); const amount = order ? (order.children.find(function (c) { return c.name === 'Amount'; }) || {}).text : ''; return { body: input.body, vars: { amount: String(amount || '0') } }; - {id: prune, type: transform, description: "Drops empty elements the upstream rejects.", kind: xml_prune, rules: [remove_empty_self_closing_elements, remove_empty_parents]} - {id: post, type: http_request, description: "Forwards the pruned document; body: transformed re-serializes the DOM as application/xml.", url: "${XML_UPSTREAM_URL}", body: transformed, timeout: 10s, error_on_status: [5xx]} - {id: ack, type: respond, description: "Acknowledges the source system.", status: 202, body: "accepted"} edges: [in>body, body>auth, auth>env, env>only_orders, only_orders>tag, tag>prune, prune>post, post>ack]