Crates
hl7-2-soap
HL7 v2 carried in a SOAP envelope over HTTP
What it is
MLLP is how HL7 v2 usually moves, and hl7-2-mllp is that transport. SOAP is the other
one — what an estate ends up with when the messages have to cross a boundary that speaks HTTP, or
when the system at the far end was built by a team who had a WSDL and no socket.
This crate is that transport, and it is deliberately the same shape as its MLLP sibling: it does the protocol and nothing else.
What it does, and what it does not
It does:
- Parse a SOAP envelope and take the single business payload out of its body.
- Faults, each carrying the HTTP status that belongs with it.
- Read a v2.xml payload, or ER7 wrapped in one, and check a payload against what the interface accepts.
- Build the reply, and read one as accepted or rejected.
- Serve a WSDL that describes the endpoint at the address it was reached on.
It does not:
No HTTP client and no HTTP server: it turns bytes into meaning and back, and leaves the socket to
whatever you already use. No HL7 validation and no format conversion either — hl7-2 and the hl7-2-from-* crates own those.
Receiving
use hl7_2_soap::{Fault, message, response};
fn handle(request_body: &str) -> (u16, String) {
match accept(request_body) {
Ok(control_id) => (200, response::success(&control_id)),
Err(fault) => (fault.status, fault.to_envelope()),
}
}
fn accept(request_body: &str) -> Result<String, Fault> {
let envelope = hl7_2_soap::parse(request_body)?;
let payload = envelope.payload()?;
message::check(payload, &["ADT_A05".to_string()], &[])?;
// ...validate and forward the payload here...
Ok(message::control_id(payload).unwrap_or_default().to_string())
}Sending
use hl7_2_soap::{message, response::{self, Outcome}};
let body = message::wrap_er7("MSH|^~\\&|APP||||1||ADT^A01|9|P|2.5");
// ...POST body with Content-Type: text/xml; charset=utf-8...
match response::evaluate(status, &reply) {
Outcome::Accepted => {}
Outcome::Rejected(reason) => eprintln!("not delivered: {reason}"),
}Note message::wrap_er7: an interface that speaks pipe-delimited ER7 rather than
v2.xml can still go over SOAP, with the message carried inside the envelope.
Three things it is opinionated about
One payload per body
SOAP permits several; no HL7 interface means several. A body with none or many is a fault rather than a silent choice of the first child.
Prefixes do not matter
The same envelope arrives as soapenv:, soap:, SOAP-ENV: or unprefixed depending on which stack sent it. Elements are matched on
their local name, so all four are read alike.
A fault carries its HTTP status
Client 400 do not retry — the request is wrong
Client.Authorization 403 do not retry — the caller is not allowed
Server 500 retry — the far side had a bad momentReading a response
There is no equivalent of MSA-1 in SOAP — there are three places to look and no
agreement about which wins. response::evaluate reads all three, in the order that
cannot be talked out of a rejection: a non-2xx status, then a Fault element (even
under HTTP 200, because some stacks answer 200 and put the refusal in the body), then a Status element, then acceptance.
Status is accepted for AA, CA, and Success. Both conventions are in the field — an implementation that echoes the HL7
acknowledgement code, and one that writes a word — and a sender that knows only one will retry
forever against an endpoint that speaks the other. The crate this one was generalised from had
exactly that split between its own receiver and its own sender.
Dependencies
One: hl7-2-xml-lite-helper, re-exported
here as xml. It reads the envelopes this crate carries, matching elements on their
local name.
It is shared rather than owned because three crates in this family needed the same XML subset and
each had written its own copy: this crate, hl7-2-from-xml-into-er7, and hl7-2-from-xsd-into-json-dictionary. One reader that keeps both text and attributes replaced all three: the audit surface is
unchanged, and there is one parser to read instead of three.
Related crates
hl7-2
HL7 v2 itself: parse, navigate, validate, modify, render
hl7-2-mllp
MLLP: HL7 v2 framed on a TCP stream
hl7-3-soap
HL7 v3 carried in a SOAP envelope over HTTP