SOAP Client Python zeep Does not pass the specified headers parameters

22 views Asked by At

Tell me where to look for the cause, or how to fix this annoying misunderstanding. When forming a client for the SOAP protocol of communication with a certain service, a zip.Transport object is created to which session=requests.Session() is passed, which is stuffed with the desired set of parameters in headers.

The analysis was carried out using a plug-in zeep.The client of the plugin that outputs outgoing and incoming requests.

The code that builds the client:

    import requests
    import zeep
    import zeep.exceptions
    from zeep import xsd
    import lxml.etree
    from lxml import etree
    
    # Plugin for analysis
    class SoapLoggingPlugin(zeep.Plugin):
        def ingress(self, envelope, http_headers, operation):
            print(f"SoapLog Ingress: {lxml.etree.tostring(
                                        envelope,
                                        pretty_print=True,
                                        encoding='utf-8',
                                    ).decode()
                                    }"
                  f"\nSoapLog Ingress Headers: {http_headers}")
            return envelope, http_headers
        def egress(self, envelope, http_headers, operation, binding_options):
            print(f"SoapLog Egress: {lxml.etree.tostring(
                                        envelope,
                                        pretty_print=True,
                                        encoding='utf-8',
                                    ).decode()
                                    }"
                f"\nSoapLog Egress Headers: {http_headers}")
            return envelope, http_headers
    
    soap_logging_plugin = SoapLoggingPlugin()
    
    _session = requests.Session()
    
    token = "Required token"
    
    requests_headers = {
        "FNS-OpenApi-Token": token,
        "FNS-OpenApi-UserToken": '',
        # "Content-Type": "application/xml; charset=UTF-8",
        # "SOAPAction": "urn:SendMessageRequest",
        # 'Connection': 'keep-alive',
    }
    
    _session.verify = False  # The server does not worry about the certificate
    _session.headers.update(requests_headers)
    
    # A proxy is required, it does not allow access to the server without it
    _session.proxies = {"http": "127.0.0.1:3128", "https": "127.0.0.1:3128"}
    
    zeep_settings = zeep.Settings(strict=False, xml_huge_tree=True)  # ,extra_http_headers=requests_headers) # Here you can slip the headlines in one more place. BUT in vain
    
    _transport =  zeep.Transport(session=_session, timeout=30)
    
    _url = get_provider_url()  # A simple url to the wsdl schema
    
    # Creating a client instance
    soap_client = zeep.Client(wsdl=npd_url, settings=zeep_settings, transport=_transport, plugins=[soap_logging_plugin])

Next, we build the contents of the parameter for the request.

message_item = xsd.Element('Message', xsd.ComplexType([xsd.Element('{xmlns:ns0}GetTaxpayerStatusRequestV2', xsd.ComplexType([xsd.Element("Inn", xsd.String())]))]))
message_value = message_item([{"Inn": "1234567890"}])
result_1 = soap_client.service.SendMessage(Message=message_value)

We are watching how the server breaks us off because it did not receive a token in headers

// Here is what is being sent, first the body, then the headers
SoapLog Egress: <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
  <soap-env:Body>
    <ns0:SendMessageRequest xmlns:ns0="urn://x-artefacts-gnivc-ru/inplat/servin/OpenApiAsyncMessageConsumerService/types/1.0">
      <ns0:Message>
        <ns1:GetTaxpayerStatusRequestV2 xmlns:ns1="xmlns:ns0">
          <Inn>1234567890</Inn>
        </ns1:GetTaxpayerStatusRequestV2>
      </ns0:Message>
    </ns0:SendMessageRequest>
  </soap-env:Body>
</soap-env:Envelope>
SoapLog Egress Headers: {'SOAPAction': '"urn:SendMessageRequest"', 'Content-Type': 'text/xml; charset=utf-8'}


\\ Here is what we get in response...
SoapLog Ingress: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <soap:Fault>
      <faultcode>soap:Server</faultcode>
      <faultstring>The required headers could not be found in the transmitted request</faultstring>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

SoapLog Ingress Headers: {'Server': 'nginx/1.14.2', 'Date': 'Tue, 19 Mar 2024 07:42:30 GMT', 'Content-Type': 'text/xml; charset=UTF-8', 'Content-Length': '312', 'Connection': 'keep-alive'}

Note the 'SOAPAction' header: '"urn:SendMessageRequest"', 'Content-Type': 'text/xml; charset=utf-8' I commented in my set to find out who is substituting them. Zeep generates a SOAPAction from the service being used (soap_client.service.SendMessage()) and Content-Type that this is an XML document

In the debugger, it is clearly visible that the headers set above in the code are in memory in the client instance in the transport.

Help me figure out the reason and find a solution.

I tried passing headers directly to the client instance

and specified the parameter when creating the

zeep.settings.Settings(strict=False, xml_huge_tree=True, extra_http_headers=requests_headers)
0

There are 0 answers