Skip to content

API Reference

Generated from the source docstrings of every name exported by the top-level soapbar package — the frozen public surface covered by the stability policy. Deeper module paths (soapbar.core.*, soapbar.contrib.*) are importable but only the names below are guaranteed by SemVer.

soapbar — Python SOAP toolkit.

__version__ module-attribute

__version__: str = _version('soapbar')

The installed soapbar version, from package metadata.

WSA_ANONYMOUS module-attribute

WSA_ANONYMOUS = (
    "http://www.w3.org/2005/08/addressing/anonymous"
)

WS-Addressing anonymous address: reply on the transport back-channel.

WSA_NONE module-attribute

WSA_NONE = 'http://www.w3.org/2005/08/addressing/none'

WS-Addressing none address: the message must not be routed anywhere.

NS module-attribute

NS = _Namespaces()

Singleton with every SOAP/WSDL/WS-* namespace URI constant (see _Namespaces).

xsd module-attribute

xsd = _TypeRegistry()

Global registry of the built-in XSD simple types, e.g. xsd.resolve("int").

SoapClient

SoapClient(
    wsdl_url: str | None = None,
    *,
    transport: HttpTransport | None = None,
    use_wsa: bool = False,
    wss_credential: Any = None,
    use_mtom: bool = False,
)

WSDL-driven SOAP client.

Three ways to construct one: SoapClient(wsdl_url) fetches and parses the WSDL (binding style, SOAP version, operations and endpoint are configured automatically); from_wsdl_string does the same from an in-memory document; manual skips WSDL entirely for endpoints where you register operations by hand.

Invoke operations with call / call_async, or through the service attribute proxy (client.service.Add(a=1, b=2)). Optional behaviours: WS-Addressing headers (use_wsa), a WS-Security UsernameToken on every call (wss_credential), and MTOM attachments (use_mtom + add_attachment).

from_file classmethod

from_file(
    path: str | Path,
    *,
    use_wsa: bool = False,
    transport: HttpTransport | None = None,
    endpoint: str | None = None,
) -> SoapClient

Build a client from a WSDL file on disk.

Args: path: Path to the WSDL document. use_wsa: Enable WS-Addressing request headers. transport: Custom HttpTransport (e.g. for timeouts, mTLS, or a stubbed transport in tests). Defaults to a plain one. endpoint: Override the service address parsed from the WSDL — handy when the WSDL lists a legacy/HTTP URL but you want HTTPS.

register_operation

register_operation(sig: OperationSignature) -> None

Register an operation signature by hand (for manual clients or to override a signature parsed from the WSDL).

close

close() -> None

Close the underlying transport's pooled HTTP client, if any.

Safe to call multiple times. Since 0.6.1 HttpTransport maintains a long-lived httpx.Client for connection reuse; calling close() releases that client and the connections it owns. Not required for correctness (the transport tolerates garbage-collection), but recommended in long-running processes that create many short-lived SoapClient instances.

aclose async

aclose() -> None

Async counterpart to close for the async transport.

add_attachment

add_attachment(
    data: bytes,
    content_type: str,
    content_id: str | None = None,
) -> str

Queue a binary attachment to be sent with the next MTOM call.

Returns the Content-ID (without angle brackets) that can be used in an <xop:Include href="cid:…"/> element inside the SOAP body. Only meaningful when use_mtom=True.

call

call(operation: str, **kwargs: Any) -> Any

Invoke operation with keyword arguments and return the parsed result.

The return shape depends on how many output parameters the operation declares — this arity-based contract is stable:

  • No output (or an empty body) → None.
  • Exactly one output parameter → that value, unwrapped (e.g. an int, str, Decimal, or a parsed complex/AnyXmlType value) — not wrapped in a dict.
  • Two or more output parameters → a dict keyed by parameter name.

A SOAP fault in the response is raised as SoapFault. (The single-output unwrapping is a deliberate ergonomic choice; callers that want a uniform mapping can read the operation's output parameter names from its OperationSignature.)

call_async async

call_async(operation: str, **kwargs: Any) -> Any

Async counterpart of call; same arity-based return contract.

Requires httpx. WS-Security and WS-Addressing headers are applied exactly as in call.

HttpTransport

HttpTransport(
    *,
    timeout: float = 30.0,
    verify_ssl: bool = True,
    client_cert: ClientCert = None,
    ca_bundle: str | None = None,
    persist_cookies: bool = True,
)

HTTP transport used by SoapClient.

Prefers httpx (sync and async, pooled connections) and falls back to stdlib urllib when httpx is not installed — the fallback supports neither client certificates nor a custom CA bundle nor async.

Construction knobs: timeout; verify_ssl (default True — the opt-out exists for test endpoints only); client_cert for mutual TLS (see load_pkcs12 for .pfx bundles); ca_bundle to pin a private/government PKI root (takes precedence over verify_ssl); and persist_cookies to keep session cookies across calls (stateful services). Use as a context manager or call close()/aclose() to release pooled connections.

cookies property

cookies: Any

The live httpx.Cookies jar this transport carries across calls.

Read a session cookie after a call (transport.cookies.get("JSESSIONID")) or inject one before (transport.cookies.set("sid", "...", domain=...)). Backed by the pooled sync client, so it persists for the session. Requires httpx.

close

close() -> None

Close the long-lived sync httpx.Client, if any. Safe to call multiple times; no-op when httpx is not installed or the client has never been created.

aclose async

aclose() -> None

Close the long-lived async httpx.AsyncClient, if any.

send

send(
    url: str, body: bytes, headers: dict[str, str]
) -> tuple[int, str, bytes]

Send SOAP request. Returns (status, content_type, body).

send_async async

send_async(
    url: str, body: bytes, headers: dict[str, str]
) -> tuple[int, str, bytes]

Send async SOAP request. Requires httpx.

fetch

fetch(url: str) -> bytes

GET request for WSDL retrieval.

BindingStyle

Bases: Enum

is_wsi_conformant property

is_wsi_conformant: bool

Return False for styles that violate WS-I Basic Profile 1.1 R2706.

RPC_ENCODED and DOCUMENT_ENCODED use SOAP Section 5 encoding, which WS-I BP 1.1 R2706 prohibits. Use them only for WITSML or other legacy protocols that explicitly require Section 5 encoding.

OperationParameter dataclass

OperationParameter(
    name: str,
    xsd_type: XsdType,
    required: bool = True,
    namespace: str | None = None,
)

An operation's input/output parameter descriptor (an immutable value object).

OperationSignature dataclass

OperationSignature(
    name: str,
    input_params: list[OperationParameter] = list(),
    output_params: list[OperationParameter] = list(),
    soap_action: str = "",
    input_namespace: str | None = None,
    output_namespace: str | None = None,
    one_way: bool = False,
    emit_rpc_result: bool = False,
)

Full description of one SOAP operation: name, input/output parameters, soapAction, and per-operation flags (one-way, rpc:result).

SoapEnvelope dataclass

SoapEnvelope(
    version: SoapVersion = SOAP_11,
    header_blocks: list[SoapHeaderBlock] | None = None,
    body_elements: list[_Element] | None = None,
    ws_addressing: WsaHeaders | None = None,
    ws_security_element: _Element | None = None,
    header_elements: list[_Element] | None = None,
)

add_header

add_header(elem: _Element | SoapHeaderBlock) -> None

Append a header block; a bare element is wrapped in a plain SoapHeaderBlock (no mustUnderstand/role attributes).

add_body_content

add_body_content(elem: _Element) -> None

Append elem as a child of the SOAP Body.

build

build() -> _Element

Build and return the Envelope element tree.

The Header element is emitted only when header blocks are present; the Body is always present.

to_string

to_string(pretty_print: bool = False) -> str

Build the envelope and serialize it to str (no XML declaration).

to_bytes

to_bytes(pretty_print: bool = False) -> bytes

Build the envelope and serialize it to UTF-8 bytes, the wire form.

SoapHeaderBlock dataclass

SoapHeaderBlock(
    element: _Element,
    must_understand: bool = False,
    relay: bool = False,
    role: str | None = None,
)

A single SOAP header block with parsed attributes (an immutable value object).

relay is parsed from the SOAP 1.2 env:relay attribute ([SOAP12-P1] §5.2.4) and exposed for inspection by intermediary implementations. soapbar acts as an ultimate receiver and does not forward envelopes, so relay is intentionally not enforced here — forwarding behaviour is the responsibility of a SOAP intermediary layer that wraps this library.

SoapVersion

Bases: Enum

SOAP protocol version (1.1 or 1.2), with per-version namespace, content type, and prefix properties.

WsaEndpointReference dataclass

WsaEndpointReference(
    address: str,
    reference_parameters: tuple[_Element, ...] = (),
)

WS-Addressing endpoint reference (an immutable value object).

reference_parameters is a tuple (not a list) so the reference is hashable and immutable.

WsaHeaders dataclass

WsaHeaders(
    message_id: str | None = None,
    to: str | None = None,
    action: str | None = None,
    from_: WsaEndpointReference | None = None,
    reply_to: WsaEndpointReference | None = None,
    fault_to: WsaEndpointReference | None = None,
    relates_to: str | None = None,
    relates_to_relationship: str = "http://www.w3.org/2005/08/addressing/reply",
)

Parsed WS-Addressing headers from a SOAP envelope.

Intentionally mutable (not frozen): the header parser fills these fields in incrementally as it walks the SOAP header blocks (see parse_wsa_headers).

SoapbarError

Bases: Exception

Base class for every error soapbar raises deliberately.

Catch this to handle any soapbar-originated failure uniformly. Note it does not encompass errors raised by the standard library or third-party dependencies (e.g. an lxml parse error on malformed XML, or an httpx connection error) — only failures soapbar itself signals.

SoapFault

SoapFault(
    faultcode: str,
    faultstring: str,
    *,
    faultactor: str | None = None,
    detail: str | _Element | None = None,
    subcodes: list[tuple[str, str]] | None = None,
)

Bases: SoapbarError

to_soap11_element

to_soap11_element() -> _Element

Render this fault as a SOAP 1.1 Fault element.

to_soap11_envelope

to_soap11_envelope(
    header_blocks: list[_Element] | None = None,
) -> _Element

Render this fault as a complete SOAP 1.1 Envelope element, optionally carrying header_blocks in the Header.

to_soap12_element

to_soap12_element() -> _Element

Render this fault as a SOAP 1.2 Fault element.

SOAP 1.1 fault codes are translated to their 1.2 equivalents (e.g. ClientSender) and subcodes are emitted as namespace-qualified QNames.

to_soap12_envelope

to_soap12_envelope(
    header_blocks: list[_Element] | None = None,
) -> _Element

Render this fault as a complete SOAP 1.2 Envelope element, optionally carrying header_blocks in the Header.

from_element classmethod

from_element(elem: _Element) -> SoapFault

Parse a Fault from a Fault element or an Envelope element.

MtomAttachment dataclass

MtomAttachment(
    content_id: str, content_type: str, data: bytes
)

A single MIME part / XOP attachment (an immutable value object).

MtomMessage dataclass

MtomMessage(
    soap_xml: bytes,
    attachments: tuple[MtomAttachment, ...] = (),
)

Parsed MTOM multipart message (an immutable value object).

attachments is a tuple (not a list) so the message is hashable and cannot be mutated in place after parsing.

AnyXmlType

Bases: XsdType

Passthrough for an xsd:any wildcard body.

The value is a string (or bytes) of XML serialized verbatim as child element(s) of the carrier, and read back as the inner-XML string. This is what document/literal bare bodies need — e.g. SEFAZ NF-e's <nfeDadosMsg> carries a raw <consStatServ> / <enviNFe> message. The actual element insertion/extraction is handled by the binding serializer; to_xml/from_xml are identity for string content.

to_xml

to_xml(value: Any) -> str

Return the raw XML string unchanged (bytes are decoded as UTF-8).

from_xml

from_xml(s: str) -> str

Return the inner-XML string unchanged.

ArrayXsdType

ArrayXsdType(
    name: str,
    element_type: XsdType,
    element_tag: str = "item",
    inline: bool = False,
    target_namespace: str = "",
    qualified: bool = False,
)

Bases: XsdType

XSD array type: a wrapper element containing repeated child elements.

to_xml

to_xml(value: Any) -> str

Unsupported: arrays have no text form — use to_element.

from_xml

from_xml(s: str) -> Any

Unsupported: arrays have no text form — use from_element.

to_element

to_element(
    tag: str,
    value: Any,
    ns: str = "",
    soap_encoding: str | None = None,
) -> Any

Serialize the list value as a wrapper element named tag.

When soap_encoding names a SOAP encoding namespace, the wrapper carries the mandated array attributes (SOAP-ENC:arrayType for 1.1, enc:itemType/enc:arraySize for 1.2).

from_element

from_element(elem: Any) -> list[Any]

Deserialize the wrapper elem's children into a list of items.

ChoiceXsdType

ChoiceXsdType(
    name: str,
    options: list[tuple[str, XsdType]],
    target_namespace: str = "",
    qualified: bool = False,
)

Bases: XsdType

XSD choice type: exactly one of the named options is present.

to_xml

to_xml(value: Any) -> str

Unsupported: choices have no text form — use to_element.

from_xml

from_xml(s: str) -> Any

Unsupported: choices have no text form — use from_element.

to_element

to_element(
    tag: str,
    value: Any,
    ns: str = "",
    soap_encoding: str | None = None,
) -> Any

Serialize value — a dict with exactly one option key set — as an element named tag containing that single option child.

from_element

from_element(elem: Any) -> dict[str, Any]

Deserialize elem into {option_name: value} for the option present; an empty dict if no known option matches.

ComplexXsdType

ComplexXsdType(
    name: str,
    fields: list[tuple[str, XsdType | str]],
    target_namespace: str = "",
    qualified: bool = False,
    registry: _TypeRegistry | None = None,
)

Bases: XsdType

XSD complexType with a sequence of named sub-elements.

Fields may be XsdType instances or string names to be lazily resolved via xsd.resolve() (for forward/recursive references).

qualified mirrors the owning schema's elementFormDefault: when True, the type's local child elements are emitted in target_namespace (what a conformant peer — zeep/.NET/Java — expects). Reading is always namespace tolerant (children are matched by local name), so soapbar accepts both qualified and unqualified input regardless of this flag.

to_xml

to_xml(value: Any) -> str

Unsupported: complex values have no text form — use to_element.

from_xml

from_xml(s: str) -> Any

Unsupported: complex values have no text form — use from_element.

to_element

to_element(
    tag: str,
    value: dict[str, Any],
    ns: str = "",
    soap_encoding: str | None = None,
) -> Any

Serialize the field dict value as an element named tag.

Child elements follow the field order; None fields of non-string types are omitted. ns qualifies the outer element; child qualification follows the type's qualified flag.

from_element

from_element(elem: Any) -> dict[str, Any]

Deserialize elem's children into a field dict.

Children are matched by local name (namespace tolerant); missing or xsi:nil fields come back as None, repeated (maxOccurs>1) fields as lists.

XsdType

Bases: ABC

to_xml abstractmethod

to_xml(value: Any) -> str

Serialize a Python value to the type's XSD lexical form.

from_xml abstractmethod

from_xml(s: str) -> Any

Parse an XSD lexical form back into the Python value.

Raises:

Type Description
ValueError

if s is not a valid lexical value for the type.

WsdlBinding dataclass

WsdlBinding(
    name: str,
    port_type: str,
    soap_ns: str = "",
    style: str = "document",
    transport: str = "",
    operations: list[WsdlBindingOperation] = list(),
)

binding_style_for

binding_style_for(operation_name: str) -> BindingStyle

Determine BindingStyle for a specific operation.

WsdlBindingOperation dataclass

WsdlBindingOperation(
    name: str,
    soap_action: str = "",
    style: str | None = None,
    use: str | None = None,
    output_use: str | None = None,
    input_namespace: str | None = None,
    output_namespace: str | None = None,
)

Per-operation SOAP binding details: soapAction, style and use overrides, and input/output body namespaces.

WsdlDefinition dataclass

WsdlDefinition(
    name: str = "",
    target_namespace: str = "",
    messages: dict[str, WsdlMessage] = dict(),
    port_types: dict[str, WsdlPortType] = dict(),
    bindings: dict[str, WsdlBinding] = dict(),
    services: dict[str, WsdlService] = dict(),
    schema_elements: list[Any] = list(),
    complex_types: dict[str, XsdType] = dict(),
    type_registry: Any = None,
    global_elements: list[Any] = list(),
)

In-memory model of a complete WSDL 1.1 document.

Produced by parse_wsdl / parse_wsdl_file and consumed by build_wsdl; messages, port types, bindings, and services are keyed by local name, with parsed schema types in complex_types.

WsdlMessage dataclass

WsdlMessage(name: str, parts: list[WsdlPart] = list())

A wsdl:message: a named list of WsdlPart entries.

WsdlOperation dataclass

WsdlOperation(
    name: str,
    documentation: str = "",
    input: WsdlOperationMessage | None = None,
    output: WsdlOperationMessage | None = None,
    faults: list[WsdlOperationMessage] = list(),
)

A wsdl:operation in a port type: name, documentation, and its input/output/fault message references.

WsdlOperationMessage dataclass

WsdlOperationMessage(message: str, name: str | None = None)

An operation's input/output/fault slot referencing a message by QName.

WsdlPart dataclass

WsdlPart(
    name: str,
    element: str | None = None,
    type: str | None = None,
    element_ns: str | None = None,
)

A wsdl:part of a message: a named reference to an element or type.

WsdlPort dataclass

WsdlPort(name: str, binding: str, address: str = '')

A wsdl:port: a binding bound to a concrete endpoint address.

WsdlPortType dataclass

WsdlPortType(
    name: str, operations: list[WsdlOperation] = list()
)

A wsdl:portType: the abstract interface, a named set of operations.

WsdlService dataclass

WsdlService(name: str, ports: list[WsdlPort] = list())

A wsdl:service: a named collection of WsdlPort entries.

SecurityValidationError

Bases: SoapbarError

Raised by UsernameTokenValidator when authentication fails.

UsernameTokenCredential dataclass

UsernameTokenCredential(
    username: str,
    password: str,
    use_digest: bool = False,
    nonce: bytes | None = None,
    created: str | None = None,
)

Holds the username and password for a WS-Security UsernameToken.

Args: username: The username to embed. password: The plain-text password. use_digest: If True, the password is hashed via PasswordDigest (SHA-1 based, per WSS 1.0 §3.2.1). If False (default), PasswordText is used. nonce: Override the random nonce bytes (mainly for testing). created: Override the creation timestamp string (mainly for testing).

UsernameTokenValidator

UsernameTokenValidator()

Bases: ABC

Abstract base class for server-side UsernameToken validation.

Subclass and implement get_password to look up the expected password for a given username. The base class handles digest verification, wsu:Timestamp expiry checking (N05), and nonce replay prevention (N07).

Subclasses that define their own __init__ MUST call super().__init__() to initialise the nonce replay cache.

get_password abstractmethod

get_password(username: str) -> str | None

Return the plain-text password for username, or None if unknown.

validate

validate(security_element: _Element) -> str

Validate a wsse:Security element and return the authenticated username.

Performs, in order: 1. wsu:Timestamp expiry check when present (N05). 2. wsse:UsernameToken credential verification. 3. Nonce replay check for PasswordDigest tokens (N07).

Raises: SecurityValidationError: if any check fails.

XmlSecurityError

Bases: SoapbarError

Raised when XML Signature verification or XML Encryption fails.

BodyTooLargeError

Bases: SoapbarError, ValueError

Raised when a request body (or a decoded/expanded form of it) exceeds the configured size limit.

Subclasses both SoapbarError (so except SoapbarError catches it like any other soapbar error) and ValueError (so existing except (ValueError, TypeError) handlers still treat it as a client error). The distinct type lets the ingress adapters recognise a size-limit breach specifically (as opposed to a malformed-input ValueError) and translate it into the standard oversized-request fault rather than a generic 500.

SoapApplication

SoapApplication(
    custom_wsdl: bytes | None = None,
    service_url: str = "http://localhost:8000/soap",
    *,
    max_body_size: int = 10 * 1024 * 1024,
    security_validator: Any = None,
    validate_body_schema: bool = False,
    allow_plaintext_credentials: bool = False,
    wsdl_access: Literal[
        "public", "authenticated", "disabled"
    ] = "public",
    wsdl_auth_hook: Callable[[dict[str, str]], bool]
    | None = None,
    enable_gzip: bool = False,
)

Framework-agnostic SOAP dispatcher: routes envelopes to services.

Register SoapService instances with register, then expose the application over HTTP through AsgiSoapApp or WsgiSoapApp (or call handle_request from a custom adapter). Serves the auto-generated (or custom_wsdl) WSDL on ?wsdl requests, subject to wsdl_access.

Hardening knobs: max_body_size (default 10 MB), request nesting-depth limits, optional WS-Security validation (security_validator), opt-in body schema validation (validate_body_schema), and opt-in HTTP gzip (enable_gzip). Construction warns when service_url is plain HTTP.

max_body_size property

max_body_size: int

The configured maximum request-body size in bytes (G01).

Exposed so the WSGI/ASGI adapters can enforce the same limit before they decompress or MTOM-decode a body — stages that run ahead of handle_request and can amplify a small body into a huge one.

register

register(service: SoapService) -> None

Register service, adding its operations to the dispatch table.

SOAPAction values are indexed both quoted and unquoted so requests from either convention dispatch correctly.

get_wsdl

get_wsdl() -> bytes

Return the WSDL document as bytes — the custom_wsdl passed at construction, or one generated from the registered services.

check_wsdl_access

check_wsdl_access(headers: dict[str, str]) -> bool

Return True if the WSDL may be served for the given request headers.

Controlled by the wsdl_access constructor parameter:

  • "public" (default) — always allowed.
  • "disabled" — always denied (returns 403).
  • "authenticated" — delegates to wsdl_auth_hook; denied if no hook is configured.

handle_request

handle_request(
    body: bytes,
    soap_action: str = "",
    content_type: str = "text/xml",
    accept_header: str = "",
    _force_oversize: bool = False,
) -> tuple[int, str, bytes]

Returns (http_status, content_type, response_body).

_force_oversize lets an adapter report an oversized request through the normal fault path when the breach was detected upstream (a raw body over the limit, a gzip bomb, or MTOM/XOP amplification) without having to materialise the offending bytes here.

AsgiSoapApp

AsgiSoapApp(soap_app: SoapApplication)

ASGI 3 application wrapping a SoapApplication.

Run it directly under any ASGI server (uvicorn app:app) or mount it inside an ASGI framework (FastAPI, Starlette). GET ?wsdl serves the WSDL; POST dispatches SOAP envelopes, decoding inbound MTOM automatically. Lifespan events are acknowledged as no-ops.

SoapMethod

Bases: Protocol

The type of a method decorated with soap_operation.

A callable carrying the __soap_operation__ signature attribute. This is the value type of SoapService.get_operations; it is part of the public API so callers can annotate against it.

SoapService

Base class for SOAP services.

Subclass it, set the __service_name__ and __tns__ class attributes, and decorate handler methods with soap_operation; parameter and return XSD types are introspected from type hints. Register instances on a SoapApplication to serve them.

Class attributes: __service_name__ (service element name), __tns__ (target namespace), __binding_style__, __soap_version__, __port_name__, and __service_url__.

get_operations

get_operations() -> dict[str, SoapMethod]

Return {operation_name: method} for all @soap_operation methods.

get_operation_signatures

get_operation_signatures() -> dict[str, OperationSignature]

Return {operation_name: OperationSignature} for all operations.

WsgiSoapApp

WsgiSoapApp(soap_app: SoapApplication)

WSGI application wrapping a SoapApplication.

The synchronous counterpart of AsgiSoapApp for WSGI servers and frameworks (gunicorn, Flask/Werkzeug mounts). GET ?wsdl serves the WSDL; POST dispatches SOAP envelopes, decoding inbound MTOM automatically.

load_pkcs12

load_pkcs12(
    path: str, password: str | None = None
) -> tuple[bytes, bytes]

Load a PKCS#12 (.pfx / .p12) bundle into PEM bytes.

Returns (cert_pem, key_pem) where cert_pem is the full certificate chain (end-entity certificate first, followed by any bundled intermediates) and key_pem is the unencrypted PKCS#8 private key. Both are held in memory only — the key is never written to disk or logged. Feed the result straight to HttpTransport::

cert_pem, key_pem = load_pkcs12("cert.pfx", "password")
transport = HttpTransport(client_cert=(cert_pem, key_pem), ca_bundle="ca.pem")

Typical use is an ICP-Brasil A1 certificate for SEFAZ NF-e. A3 (hardware token) certificates are out of scope. Requires the cryptography package (install soapbar[security]).

get_serializer

get_serializer(
    style: BindingStyle, soap_version: Any = None
) -> BindingSerializer

Return a serializer for style.

For encoded styles (G05), pass soap_version (a SoapVersion enum value) so the serializer can emit the correct array attributes for SOAP 1.1 vs 1.2.

build_fault

build_fault(
    version: SoapVersion,
    faultcode: str,
    faultstring: str,
    *,
    faultactor: str | None = None,
    detail: str | _Element | None = None,
) -> _Element

Build a complete fault Envelope element for version.

faultcode uses SOAP 1.1 vocabulary (Client, Server, …) and is translated to the SOAP 1.2 equivalent automatically when needed.

build_request

build_request(
    version: SoapVersion,
    body_elements: list[_Element],
    header_elements: list[_Element] | None = None,
) -> _Element

Build a request Envelope element with the given body and headers.

build_response

build_response(
    version: SoapVersion,
    body_elements: list[_Element],
    header_elements: list[_Element] | None = None,
) -> _Element

Build a response Envelope element; structurally identical to build_request (SOAP responses differ only in body content).

build_wsa_response_headers

build_wsa_response_headers(
    request_wsa: WsaHeaders, action: str | None = None
) -> list[_Element]

Build WS-Addressing 1.0 response header elements.

Per WS-Addressing 1.0 Core [W3C Rec 2006] §3.4:

  • wsa:MessageID — a new UUID URN identifying this response message
  • wsa:RelatesTo — the wsa:MessageID of the request (if present), with RelationshipType implicitly wsa:Reply
  • wsa:Action — the response action URI (if action is provided)

The caller is responsible for deriving the action string. A common convention is to append "Response" to the request action URI.

http_headers

http_headers(
    version: SoapVersion, soap_action: str = ""
) -> dict[str, str]

Return the HTTP headers for a SOAP request in version.

SOAP 1.1 carries the action in a quoted SOAPAction header; SOAP 1.2 carries it as the action parameter of the Content-Type.

build_mtom

build_mtom(
    soap_xml: bytes,
    attachments: list[MtomAttachment],
    soap_version_content_type: str = "application/soap+xml",
    soap_action: str = "",
) -> tuple[bytes, str]

Package a SOAP envelope and binary attachments as an MTOM multipart message.

For each attachment a <xop:Include> element is NOT automatically inserted — callers are expected to have already placed <xop:Include href="cid:…"/> elements inside the SOAP body where they want binary data substituted. This function simply assembles the MIME package.

Args: soap_xml: The SOAP XML bytes (may already contain xop:Include references). attachments: List of binary attachments to include as MIME parts. soap_version_content_type: text/xml (SOAP 1.1) or application/soap+xml (SOAP 1.2). soap_action: Optional SOAPAction / action URI for the start-info parameter.

Returns: A (body_bytes, content_type_header) tuple ready for use as an HTTP body.

extract_xop_elements

extract_xop_elements(
    xml_bytes: bytes,
) -> list[tuple[str, Any]]

Return a list of (parent_tag, xop_include_element) tuples found in xml_bytes. Useful for inspecting which elements contain XOP references before resolving them.

parse_mtom

parse_mtom(
    raw: bytes,
    content_type: str,
    max_resolved_size: int | None = None,
) -> MtomMessage

Parse a multipart/related MTOM message.

The first MIME part is expected to be the SOAP envelope (application/xop+xml). Subsequent parts are binary attachments. All <xop:Include> elements in the envelope are resolved inline so that the returned soap_xml is a plain XML document that the rest of the stack can handle without special cases.

Args: raw: The raw HTTP response/request body (all MIME parts concatenated). content_type: The value of the Content-Type header for the whole body. max_resolved_size: If given, cap the size of the XOP-resolved envelope. A message with many <xop:Include> references to a large attachment can inflate to far more than the raw body (XOP amplification); exceeding this bound raises BodyTooLargeError instead of expanding it in memory.

Returns: An MtomMessage with resolved XML and the tuple of attachments.

Raises: ValueError: If the message cannot be parsed as a valid MTOM envelope. BodyTooLargeError: If the resolved envelope exceeds max_resolved_size.

build_wsdl

build_wsdl(defn: WsdlDefinition, address: str) -> _Element

Build a WSDL 1.1 document element from defn.

Parameters:

Name Type Description Default
defn WsdlDefinition

The definition to serialize (as built from service classes or parsed from another WSDL).

required
address str

The service endpoint URL, emitted in soap:address.

required

Returns:

Type Description
_Element

The wsdl:definitions root element.

build_wsdl_bytes

build_wsdl_bytes(
    defn: WsdlDefinition, address: str
) -> bytes

Build the WSDL for defn and serialize it to UTF-8 bytes (see build_wsdl).

build_wsdl_string

build_wsdl_string(
    defn: WsdlDefinition, address: str
) -> str

Build the WSDL for defn and serialize it to str (see build_wsdl).

parse_wsdl

parse_wsdl(
    source: str | bytes | Path | _Element,
    base_url: str | None = None,
    _visited: set[str] | None = None,
    allow_remote_imports: bool = False,
    allow_local_imports: bool = False,
    strict: bool = True,
    _registry: _TypeRegistry | None = None,
) -> WsdlDefinition

Parse a WSDL document from source.

allow_remote_imports controls whether wsdl:import / xsd:import elements whose resolved location starts with http:// or https:// are fetched. It defaults to False to prevent Server-Side Request Forgery (SSRF) when parsing WSDLs from untrusted sources. Set it to True only when the WSDL originates from a trusted location and remote imports are expected.

allow_local_imports controls whether imports that resolve to a local file (file:// or a filesystem path) are read. It defaults to False so that a hostile <import location="file:///etc/passwd"> in an in-memory or remote WSDL cannot exfiltrate local files. parse_wsdl_file enables it, since a trusted on-disk WSDL legitimately references sibling documents; pass it explicitly only for equally trusted local content.

strict (default True) controls error handling for import resolution failures. When False, a failed wsdl:import emits a UserWarning and is skipped rather than raising an exception. This is useful for parsing real-world WSDLs from SAP, Oracle, or government services that reference unavailable or locally absent import targets. Note: the SSRF guard (blocking remote imports) is always enforced regardless of this flag.

parse_wsdl_file

parse_wsdl_file(
    path: str | Path, strict: bool = True
) -> WsdlDefinition

Parse a WSDL document from a local file.

Unlike parse_wsdl on in-memory or remote content, imports that resolve to local files are allowed: a WSDL on disk is trusted to reference its sibling documents. Remote (http(s)://) imports remain blocked. With strict=False, unresolvable imports are skipped instead of raising.

build_binary_security_token

build_binary_security_token(
    certificate: Any, *, token_id: str = "X509Token-1"
) -> _Element

Build a wsse:BinarySecurityToken from an X.509 certificate.

The certificate is DER-encoded then Base64-encoded per WS-I BSP 1.1 R3029 (ValueType) and R3031 (EncodingType). The wsu:Id attribute is set so that a wsse:SecurityTokenReference can reference this element by URI fragment.

Args: certificate: A cryptography X.509 certificate object. token_id: Value for the wsu:Id attribute (default "X509Token-1").

Returns: A wsse:BinarySecurityToken lxml element.

Raises: ImportError: If cryptography is not installed.

build_security_header

build_security_header(
    credential: UsernameTokenCredential,
    *,
    soap_ns: str | None = None,
    timestamp_ttl: int | None = None,
) -> _Element

Build a wsse:Security header element for credential.

Returns a wsse:Security element ready to be added as a SOAP header. Per WS-Security 1.0 §6.1, the Security header MUST carry {soap_ns}mustUnderstand="1" so intermediaries know to process it. Pass soap_ns as the SOAP envelope namespace URI to enable this attribute.

Args: credential: The UsernameToken credential to embed. soap_ns: SOAP envelope namespace URI; when set, adds mustUnderstand="1". timestamp_ttl: If given, prepend a wsu:Timestamp with wsu:Created and wsu:Expires (set to now + timestamp_ttl seconds). Enables replay-window enforcement on the receiver side (N05).

decrypt_body

decrypt_body(
    envelope_bytes: bytes,
    private_key: Any,
    *,
    allow_unauthenticated_cbc: bool = False,
) -> bytes

Decrypt the SOAP Body content encrypted by encrypt_body.

The body cipher is read from the xenc:EncryptionMethod algorithm. AES-256-GCM (the default produced by encrypt_body) is authenticated: a tampered ciphertext fails the tag check and is rejected.

Legacy AES-256-CBC is unauthenticated — it is malleable and, because a distinguishable unpadding error is a padding oracle, unsafe to decrypt for an attacker who can observe outcomes. It is therefore refused by default; pass allow_unauthenticated_cbc=True only to interoperate with a peer that still emits CBC and only when you accept that risk.

Args: envelope_bytes: The SOAP envelope with an encrypted Body as bytes. private_key: The recipient's cryptography RSA private key. allow_unauthenticated_cbc: Permit decrypting legacy AES-256-CBC.

Returns: The envelope with the decrypted Body content as bytes.

Raises: ImportError: If cryptography is not installed. XmlSecurityError: If decryption fails, the ciphertext is tampered, or an unauthenticated CBC body is refused.

encrypt_body

encrypt_body(
    envelope_bytes: bytes, recipient_public_key: Any
) -> bytes

Encrypt the SOAP Body content using XML Encryption (AES-256-GCM + RSA-OAEP).

The Body's child elements are replaced with an xenc:EncryptedData element. The AES-256 session key is wrapped with RSA-OAEP (SHA-256) using recipient_public_key.

The body cipher is AES-256-GCM (XML-Enc 1.1), an authenticated mode: the 16-byte GCM tag lets the recipient detect any tampering of the ciphertext. The previous AES-256-CBC output was unauthenticated, which exposed both ciphertext malleability and a padding oracle; GCM closes both.

Args: envelope_bytes: The SOAP envelope XML as bytes. recipient_public_key: A cryptography RSA public key object.

Returns: The envelope with an encrypted Body as bytes.

Raises: ImportError: If cryptography is not installed. XmlSecurityError: If encryption fails.

extract_certificate_from_security

extract_certificate_from_security(
    security_element: _Element,
) -> Any

Extract the X.509 certificate from a wsse:BinarySecurityToken.

Args: security_element: The wsse:Security element from the SOAP header.

Returns: A cryptography X.509 certificate object.

Raises: ImportError: If cryptography is not installed. XmlSecurityError: If no BST is found or the certificate cannot be decoded.

sign_element_by_id

sign_element_by_id(
    doc_bytes: bytes,
    id_value: str,
    private_key: Any,
    certificate: Any,
    *,
    id_attr: str = "Id",
    signature_method: str = "rsa-sha256",
    digest_method: str = "sha256",
    c14n: str = "exclusive",
    end_cert_only: bool = True,
) -> bytes

Sign one internal element of a document, selected by its Id.

Unlike sign_envelope (which covers the whole SOAP envelope), this produces an enveloped ds:Signature with a single ds:Reference whose URI is #<id_value> — the standard XML-DSIG pattern for signing an inner element. The ds:Signature is appended to the document root, so for a <NFe><infNFe Id="NFe…">…</infNFe></NFe> document the signature becomes a sibling of <infNFe>.

The defaults (RSA-SHA256 / SHA-256 / Exclusive C14N) suit modern services. SEFAZ NF-e mandates the legacy set — pass signature_method="rsa-sha1", digest_method="sha1", c14n="inclusive" (the REC-xml-c14n-20010315 algorithm) and keep end_cert_only=True (only the end-entity certificate in KeyInfo/X509Data, no KeyValue).

Args: doc_bytes: The XML document containing the target element. id_value: The value of the target element's id attribute (e.g. the NFe + 44-char access key for NF-e). private_key: A cryptography private key (or PEM bytes). certificate: The signing X.509 certificate (object or PEM bytes). id_attr: Name of the attribute that holds the id. Default "Id". signature_method: "rsa-sha256" (default) or "rsa-sha1". digest_method: "sha256" (default) or "sha1". c14n: "exclusive" (default) or "inclusive" (C14N 1.0, http://www.w3.org/TR/2001/REC-xml-c14n-20010315). end_cert_only: When True (default) KeyInfo carries only the end-entity certificate and no KeyValue.

Returns: The signed document as bytes.

Raises: ImportError: If signxml is not installed. ValueError: If an algorithm option is unsupported. XmlSecurityError: If signing fails.

sign_envelope

sign_envelope(
    envelope_bytes: bytes,
    private_key: Any,
    certificate: Any,
) -> bytes

Sign a SOAP envelope with an XML Digital Signature (XML-DSIG).

The ds:Signature element is inserted into the envelope using the enveloped-signature transform (W3C XML-DSIG §8.1). RSA-SHA256 with SHA-256 digest is used by default.

Args: envelope_bytes: The SOAP envelope XML as bytes. private_key: A cryptography RSA/EC private key object. certificate: A cryptography X.509 certificate object (or a PEM bytes string) whose public key corresponds to private_key.

Returns: The signed envelope as bytes.

Raises: ImportError: If signxml is not installed. XmlSecurityError: If signing fails.

sign_envelope_bsp

sign_envelope_bsp(
    envelope_bytes: bytes,
    private_key: Any,
    certificate: Any,
    *,
    token_id: str = "X509Token-1",
) -> bytes

Sign a SOAP envelope using the WS-I BSP 1.1 X.509 token profile.

Inserts a wsse:BinarySecurityToken (DER-encoded X.509 certificate) into the wsse:Security SOAP header, then applies an enveloped XML-DSIG signature. The ds:Signature/ds:KeyInfo is rewritten to use a wsse:SecurityTokenReference/wsse:Reference that points to the token via wsu:Id, as required by WS-I BSP 1.1.

Args: envelope_bytes: The SOAP envelope XML as bytes. private_key: A cryptography RSA/EC private key. certificate: The corresponding cryptography X.509 certificate. token_id: The wsu:Id value assigned to the BST and referenced from the signature (default "X509Token-1").

Returns: The signed envelope bytes with BSP-conformant key reference.

Raises: ImportError: If signxml or cryptography is not installed. XmlSecurityError: If signing fails.

verify_envelope

verify_envelope(
    envelope_bytes: bytes,
    certificate: Any,
    *,
    expected_references: int | None = None,
    require_signed_body: bool = True,
) -> bytes

Verify the XML Digital Signature on a SOAP envelope.

Not wired into SoapApplication.handle_request automatically — callers integrating XML Signature verification MUST invoke this function explicitly. For production use, also pass expected_references matching the number of ds:Reference elements the signer pinned (e.g. 2 for Body + Timestamp); this prevents an attacker from dropping references and still getting a successful verify.

By default (require_signed_body=True) the function fails closed unless the signature actually covers the SOAP Body. Without this, a signature over only, say, the Timestamp verifies successfully and a caller could then trust an unsigned Body — the classic reference-stripping / partial-coverage weakness.

Envelopes carrying duplicate wsu:Id values are rejected before verification as a signature-wrapping countermeasure (WSS 1.0 §4.3; masterprompt §18.5).

Args: envelope_bytes: The signed SOAP envelope as bytes. certificate: The expected signer's cryptography X.509 certificate or PEM bytes used to verify the signature. expected_references: If set, the number of ds:Reference elements the verifier must see inside ds:SignedInfo. Mismatch fails verification. Default None preserves pre-0.5.5 behavior. require_signed_body: If True (default), reject a signature that does not cover the SOAP Body. Set False only when a partial-coverage signature is deliberately expected.

Returns: The verified (signed) content as bytes — the subtree the signature actually covers. Callers MUST act on this returned value, not on the original envelope_bytes, so that only signed data is trusted.

Raises: ImportError: If signxml is not installed. XmlSecurityError: If signature verification fails, the signature does not cover the Body (when required), or the envelope contains duplicate wsu:Id values.

verify_envelope_bsp

verify_envelope_bsp(
    envelope_bytes: bytes,
    *,
    expected_references: int | None = None,
    require_signed_body: bool = True,
    trusted_certs: Any = None,
    ca_certs: Any = None,
    verify_cert_trust: bool = True,
) -> bytes

Verify a SOAP envelope signed with the WS-I BSP 1.1 X.509 token profile.

Extracts the wsse:BinarySecurityToken certificate from the wsse:Security header and uses it to verify the enveloped ds:Signature.

Trust anchor (GHSA-859w-52fx-hcm6). The certificate is carried in the message, so on its own it proves only that the envelope was signed by whoever supplied it — not by a trusted party. Verifying the signature against that certificate without establishing trust is a signature-forgery / authentication bypass. This function therefore fails closed: you must anchor trust with trusted_certs (pin the expected signer certificate(s)) and/or ca_certs (accept certificates issued by trusted CA(s)). Only pass verify_cert_trust=False to deliberately accept the embedded certificate unconditionally (INSECURE — e.g. tests).

Not wired into SoapApplication.handle_request automatically — callers integrating BSP verification MUST invoke this function explicitly. For production use, also pass expected_references matching the number of ds:Reference elements the signer pinned (e.g. 2 for Body + Timestamp); this prevents an attacker from dropping references and still getting a successful verify.

Like verify_envelope, by default (require_signed_body=True) it fails closed unless the signature covers the SOAP Body, defeating reference-stripping / partial-coverage signatures.

Envelopes carrying duplicate wsu:Id values are rejected before verification as a signature-wrapping countermeasure (WSS 1.0 §4.3; masterprompt §18.5).

Args: envelope_bytes: The signed SOAP envelope as bytes. expected_references: If set, the number of ds:Reference elements the verifier must see inside ds:SignedInfo. Mismatch fails verification. Default None preserves pre-0.5.5 behavior. require_signed_body: If True (default), reject a signature that does not cover the SOAP Body. Set False only when a partial-coverage signature is deliberately expected. trusted_certs: Iterable of pinned signer certificates (cryptography X.509 objects or PEM/DER bytes); the embedded certificate must equal one of them. ca_certs: Iterable of trusted issuer CA certificates; the embedded certificate must be directly issued by one of them. verify_cert_trust: If True (default), enforce the trust anchor above. Set False to accept the embedded certificate unconditionally (INSECURE).

Returns: The verified (signed) content as bytes — the subtree the signature actually covers. Callers MUST act on this returned value, not on the original envelope_bytes.

Raises: ImportError: If signxml or cryptography is not installed. XmlSecurityError: If signature verification fails, the signature does not cover the Body (when required), no token is found, or the envelope contains duplicate wsu:Id values.

local_name

local_name(elem: _Element) -> str

Return the tag name of elem without its namespace ({ns}locallocal).

namespace_uri

namespace_uri(elem: _Element) -> str | None

Return the namespace URI of elem's tag, or None if it has none.

parse_xml

parse_xml(data: str | bytes) -> _Element

Parse an XML document from a string or bytes with the hardened parser.

The parser refuses entity expansion, DTDs, and network access (XXE/SSRF protection) and strips comments and processing instructions.

Parameters:

Name Type Description Default
data str | bytes

The XML document; str input is encoded as UTF-8.

required

Returns:

Type Description
_Element

The document's root element.

Raises:

Type Description
lxml.etree.XMLSyntaxError

if data is not well-formed XML.

parse_xml_document

parse_xml_document(
    source: str | bytes | Path | _Element,
) -> _Element

Return the root element for source, whatever its form.

Accepts a raw XML string or bytes, a filesystem Path, or an already-parsed element (returned unchanged). String and file input go through the hardened parser (see parse_xml).

to_bytes

to_bytes(
    elem: _Element,
    pretty_print: bool = False,
    xml_declaration: bool = True,
) -> bytes

Serialize elem to UTF-8 bytes, by default with an XML declaration.

This is the form to put on the wire; use to_string for logging or embedding in text.

to_string

to_string(
    elem: _Element, pretty_print: bool = False
) -> str

Serialize elem to a str, without an XML declaration.

soap_operation

soap_operation(
    *,
    name: str | None = None,
    input_params: list[OperationParameter] | None = None,
    output_params: list[OperationParameter] | None = None,
    soap_action: str | None = None,
    documentation: str = "",
    one_way: bool = False,
    emit_rpc_result: bool = False,
) -> Callable[[Callable[..., Any]], Callable[..., Any]]

Decorator that marks a method as a SOAP operation.