Soap
libraryMinimal SOAP 1.1 client: posts an XML envelope to an endpoint and gives back the response body as a string, plus an XPath helper to pick values out of it. There is no WSDL support; build the envelope yourself. Things to know: only the body text is returned, so the HTTP status is not available, and a SOAP Fault (usually HTTP 500) comes back like any other response, so check the XML for a Fault. Network failures raise "Api request failed: ...". There are no timeout, cookie or authentication helpers; add an Authorization header through the headers argument. TLS certificates are always verified; use clientCertificate() for mutual TLS. Credentials belong in secrets: secret("name").
- Kind Library, a global in every script
- Category APIs & Data
- Functions 4
Functions
-
poststring Posts a SOAP envelope to the endpoint and returns the response body as a string. -
clientCertificateself Registers a PKCS#12 (.p12/.pfx) client certificate for mutual TLS. -
certself Alias for clientCertificate(host, port, file, passphrase). -
xpathstring Evaluates an XPath 1.0 expression on an XML string and returns the result as a string: the text of the first matching node, or the string form of a number, boolean or string expression (count(//Item) gives "3").
post()
Section titled “post()”Soap.post(soapUrl: string, requestMessage: string, SOAPAction: string, doFormat: boolean)→stringSoap.post(soapUrl: string, requestMessage: string, SOAPAction: string, headers: table, doFormat: boolean)→string Posts a SOAP envelope to the endpoint and returns the response body as a string. Sets the headers "Content-Type: text/xml;charset=UTF-8" and "SOAPAction: ACTION" (the action is sent as given, without added quotes; pass "" for none). Entries in the optional headers table replace those defaults, which is how you switch to SOAP 1.2 ("Content-Type: application/soap+xml") or add an Authorization header. The request is encoded as UTF-8, the response is read as UTF-8 and carriage returns are removed. The last argument is required: with doFormat true the response is pretty-printed, with false it is returned as received. Formatting only changes the indentation; entities such as & keep their meaning. With four arguments the fourth is always doFormat; to pass headers use all five. The HTTP status is not returned, and error statuses do not raise: a SOAP Fault is just the response body. Connection problems and timeouts raise "Api request failed: ...".
Parameters
-
soapUrlstring - The URL of the SOAP endpoint
-
requestMessagestring - The complete SOAP envelope as an XML string
-
SOAPActionstring - Value of the SOAPAction header; "" for none
-
headerstable - Extra request headers. A map ({["Content-Type"] = "application/soap+xml"}) replaces the default header of that name; a list of "Name:value" strings adds headers
-
doFormatboolean - true to pretty-print the response, false to return it as received
Returns
Example
Call a service with an Authorization header and check the result
local envelope = [[<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ord="urn:orders"> <soapenv:Body> <ord:GetOrder><ord:OrderId>1001</ord:OrderId></ord:GetOrder> </soapenv:Body></soapenv:Envelope>]]
local response = Soap.post( "https://erp.example.com/services/orders", envelope, "urn:orders/GetOrder", { Authorization = "Bearer " .. secret("erp_token") }, false)Assert.equals("", Soap.xpath(response, "//*[local-name()='Fault']"))print(Soap.xpath(response, "//*[local-name()='Status']"))clientCertificate()
Section titled “clientCertificate()”Soap.clientCertificate(host: string, port: number, file: string, passphrase: string)→self Registers a PKCS#12 (.p12/.pfx) client certificate for mutual TLS. It is presented only on requests to the given host and port (a URL without a port means 443 for https and 80 for http); calling it again for the same host and port replaces the certificate. The file is read from the project (fetched from the Reflex server when it is not in the workspace). A copy fetched from the server is removed from the workspace after loading; a file that was already in the workspace is left alone. Raises "Failed to configure client certificate: ..." when the port is outside 1-65535, the file is missing, or the passphrase is wrong. Use secret() for the passphrase.
Parameters
-
hoststring - Host name of the HTTPS endpoint, without scheme or port
-
portnumber - Port of the endpoint, 1-65535
-
filestring - PKCS#12 file in the project
-
passphrasestring - Passphrase of the file; nil is treated as an empty one
Returns
Example
Soap.clientCertificate("soap.partner.example", 443, "certs/client.p12", secret("client_cert_passphrase"))local response = Soap.post("https://soap.partner.example/service", "<Envelope/>", "", false)cert()
Section titled “cert()”Soap.cert(host: string, port: number, file: string, passphrase: string)→self Alias for clientCertificate(host, port, file, passphrase).
Parameters
-
hoststring - Host name of the HTTPS endpoint, without scheme or port
-
portnumber - Port of the endpoint, 1-65535
-
filestring - PKCS#12 file in the project
-
passphrasestring - Passphrase of the file; nil is treated as an empty one
Returns
xpath()
Section titled “xpath()”Soap.xpath(in: string, xpath: string)→stringSoap.xpath(in: string, xpath: string, namespaces?: table)→string Evaluates an XPath 1.0 expression on an XML string and returns the result as a string: the text of the first matching node, or the string form of a number, boolean or string expression (count(//Item) gives "3"). Returns "" when nothing matches. Raises an error when the XML cannot be parsed or the expression is invalid. The XML is parsed with namespace support. Prefixes declared in the document can be used in the expression (//ord:OrderId), and a third argument maps extra prefixes to namespace URIs, which is the way to address elements in a default namespace (xmlns="urn:orders") because XPath 1.0 has no default namespace. Matching on the local name keeps working: //*[local-name()='OrderId']. A name without a prefix only matches elements that are in no namespace. Entities are decoded, so an ampersand comes back as "&".
Parameters
-
instring - The XML document as a string
-
xpathstring - The XPath 1.0 expression
-
namespacestable optional - Extra namespace prefixes as a table `{ prefix = "uri" }`, added to the prefixes declared in the document
Returns
Example
local xml = '<Envelope><Body><GetOrderResponse><OrderId>42</OrderId><Status>SHIPPED</Status></GetOrderResponse></Body></Envelope>'print(Soap.xpath(xml, "//OrderId"))print(Soap.xpath(xml, "count(//*)"))local ns = '<o:Order xmlns:o="urn:orders"><o:Id>7</o:Id></o:Order>'print(Soap.xpath(ns, "//o:Id"))print(Soap.xpath('<Order xmlns="urn:orders"><Id>8</Id></Order>', "//x:Id", { x = "urn:orders" }))