SOAP Source
Expose a SOAP web service endpoint to receive XML-based messages from legacy healthcare systems.
Overview
The SOAP source creates an HTTP server that exposes a SOAP web service endpoint. It parses incoming SOAP envelopes, extracts the body payload, and passes it into the channel pipeline for validation and transformation.
Many healthcare systems, particularly older EHR platforms, clinical document repositories, and public health reporting systems, still rely on SOAP-based web services for interoperability. This source enables intu to act as a SOAP service provider, receiving CDA documents, IHE transactions, and other XML-based clinical data.
wsdl_path, intu will serve it at the endpoint's ?wsdl URL, allowing clients to auto-discover the service contract.
Configuration
listener:
type: soap
soap:
port: 8443
wsdl_path: ./schemas/clinical-document.wsdl
service_name: ClinicalDocumentService
tls:
cert_file: /etc/intu/certs/server.crt
key_file: /etc/intu/certs/server.key
auth:
type: basic
username: ${SOAP_USER}
password: ${SOAP_PASS}
Properties
?wsdl query parameter.id.cert_file and key_file.basic (username/password) and wsse (WS-Security UsernameToken) types.Auth Type Details
| Type | Properties | Description |
|---|---|---|
basic |
username, password |
HTTP Basic authentication applied to the SOAP endpoint. |
wsse |
username, password, nonce (bool) |
WS-Security UsernameToken profile. When nonce is true, a nonce and timestamp are required in the security header. |
Complete Example
A SOAP endpoint that receives CDA (Clinical Document Architecture) documents from an EHR system and transforms them into FHIR DocumentReference resources.
id: cda-document-receiver
enabled: true
listener:
type: soap
soap:
port: 8443
wsdl_path: ./schemas/clinical-document.wsdl
service_name: ClinicalDocumentService
tls:
cert_file: /etc/intu/certs/server.crt
key_file: /etc/intu/certs/server.key
auth:
type: basic
username: ${SOAP_USER}
password: ${SOAP_PASS}
validator:
runtime: node
entrypoint: validator.ts
transformer:
runtime: node
entrypoint: transformer.ts
destinations:
- fhir-document-store
- audit-log
TypeScript Transformer Example
This transformer processes a SOAP XML payload containing a CDA document and extracts key metadata into a FHIR DocumentReference resource.
import { Message, TransformResult } from "@intu/sdk";
function extractElement(xml: string, tag: string): string {
const regex = new RegExp(`<${tag}[^>]*>([^<]*)</${tag}>`);
const match = xml.match(regex);
return match ? match[1].trim() : "";
}
function extractAttribute(xml: string, tag: string, attr: string): string {
const regex = new RegExp(`<${tag}[^>]*${attr}="([^"]*)"[^>]*/?>`);
const match = xml.match(regex);
return match ? match[1] : "";
}
export default function transform(msg: Message): TransformResult {
const soapXml = msg.body as string;
const bodyMatch = soapXml.match(
/<(?:\w+:)?Body[^>]*>([\s\S]*?)<\/(?:\w+:)?Body>/
);
if (!bodyMatch) {
return { success: false, error: "Could not extract SOAP Body" };
}
const bodyContent = bodyMatch[1];
const documentId = extractAttribute(bodyContent, "id", "root");
const title = extractElement(bodyContent, "title");
const effectiveTime = extractAttribute(bodyContent, "effectiveTime", "value");
const patientId = extractAttribute(bodyContent, "patientRole", "extension")
|| extractAttribute(bodyContent, "id", "extension");
const authorName = extractElement(bodyContent, "assignedPerson");
const typeCode = extractAttribute(bodyContent, "code", "code");
const typeSystem = extractAttribute(bodyContent, "code", "codeSystem");
const typeDisplay = extractAttribute(bodyContent, "code", "displayName");
const documentReference = {
resourceType: "DocumentReference",
masterIdentifier: {
system: "urn:ietf:rfc:3986",
value: `urn:oid:${documentId}`,
},
status: "current",
type: {
coding: [
{
system: mapOidToUri(typeSystem),
code: typeCode,
display: typeDisplay,
},
],
},
subject: {
identifier: {
system: "urn:oid:2.16.840.1.113883.19.5",
value: patientId,
},
},
date: formatCdaDate(effectiveTime),
description: title,
content: [
{
attachment: {
contentType: "text/xml",
data: Buffer.from(bodyContent).toString("base64"),
},
format: {
system: "urn:oid:1.3.6.1.4.1.19376.1.2.3",
code: "urn:ihe:iti:xds:2017:mimeTypeSufficient",
},
},
],
};
return {
success: true,
body: JSON.stringify(documentReference),
contentType: "application/fhir+json",
};
}
function mapOidToUri(oid: string): string {
const oidMap: Record<string, string> = {
"2.16.840.1.113883.6.1": "http://loinc.org",
"2.16.840.1.113883.6.96": "http://snomed.info/sct",
};
return oidMap[oid] || `urn:oid:${oid}`;
}
function formatCdaDate(raw: string): string {
if (!raw || raw.length < 8) return new Date().toISOString();
return `${raw.slice(0, 4)}-${raw.slice(4, 6)}-${raw.slice(6, 8)}`;
}