Debugging¶
The security pages tell you how to keep stack traces away from clients; this page is the other direction — how to see what actually went over the wire when an integration misbehaves.
See the envelopes¶
Three loggers carry the traffic, named after their modules:
| Logger | Emits |
|---|---|
soapbar.client.client |
operation dispatch; request and response envelopes, status, content type (logged on the client side of the transport seam, so a custom or in-process transport is covered too) |
soapbar.client.transport |
transport-level events: which HTTP path was taken (httpx or the urllib fallback), MTOM/XOP response decoding |
soapbar.server.application |
inbound dispatch on the server side |
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger("soapbar.client").setLevel(logging.DEBUG)
Envelopes are redacted before they reach a log record — wsse:Security
blocks are emptied and password-like elements are blanked wherever they
appear — but redaction is best-effort: treat client DEBUG as something you
enable deliberately, for a bounded period, against a log sink you control
(see Security).
To inspect an envelope you are building, print it directly:
from soapbar.core.envelope import SoapEnvelope, SoapVersion
env = SoapEnvelope(version=SoapVersion.SOAP_11)
print(env.to_string(pretty_print=True))
The failures you will actually hit¶
The response is not SOAP at all. A proxy error page, an auth challenge,
a gateway's JSON error. The client raises NonSoapResponseError carrying
the HTTP status, the content type, and a truncated body excerpt — read the
excerpt first; it usually names the real problem (a 407, a redirect to a
login page, a WAF block).
Namespace off-by-one. The service faults with "unknown operation" or
ignores your parameters even though the local names look right. Compare the
xmlns on your wrapper element against the WSDL's targetNamespace
character by character — a trailing slash or an http/https mismatch is
enough. The DEBUG envelope shows exactly what was sent.
SOAPAction quoting. Some stacks require the action quoted
(SOAPAction: "urn:op"), some unquoted, and some empty-but-present
(SOAPAction: ""). soapbar's server indexes both quoted and unquoted forms;
other stacks may not. If a request dispatches in a test tool but not from
code, diff this header first.
Binding style divergence. A doc/literal-wrapped client calling an RPC/literal service (or vice versa) produces bodies that look similar and dispatch nowhere. The client auto-detects style from the WSDL; when there is no WSDL, make the style explicit and compare against a known-good request from the service's own documentation.
Unknown operation on the client. call() raises ValueError (naming
the known operations) instead of silently sending an empty wrapper;
client.service.Tpyo(...) raises AttributeError. If you meant to send an
unregistered, argument-less probe deliberately, pass allow_unknown=True.
Schema validation faults. With validate_body_schema=True, a
Client fault beginning Schema validation failed: carries the first
schema error verbatim — element form (qualified vs unqualified children) and
lexical type errors are the two usual causes; see
WSDL schema validation.
Server-side: seeing errors without leaking them¶
Unhandled handler exceptions return "An internal error occurred." to the
client by design. The full traceback goes to the
soapbar.server.application logger — point it at your sink:
logging.getLogger("soapbar.server.application").setLevel(logging.DEBUG)
Keep the scrubbing in production; debug with the log, not the fault body.