Making a SOAP request using Python requests module

前端 未结 4 1121
滥情空心
滥情空心 2021-02-06 14:48

I used python requests module for REST requests.

I am trying to make a soap request but I wondered couldn’t get an example for this . Here is My soap body and headers.

相关标签:
4条回答
  • 2021-02-06 15:03

    To work with a SOAP server you should use a specialized library. Unfortunately, there is no good SOAP client modules for Python, the best one I've used is suds.

    0 讨论(0)
  • 2021-02-06 15:04

    This is largely hypothetical since I'm not aware of anyone actually having implemented it but suds supports making custom implementations of suds.transport.Transport. Once such is suds.transport.http.HttpTransport. So technically by implementing a transport subclass you could create a suds transport that uses requests.

    http://jortel.fedorapeople.org/suds/doc/suds.transport.http.HttpTransport-class.html is what's used by default and it returns http://jortel.fedorapeople.org/suds/doc/suds.transport.Reply-class.html so as you can see, it should be fairly simple to wrap requests replies so that suds understands them. Transport request (that should be sent with requests) is documented here http://jortel.fedorapeople.org/suds/doc/suds.transport.Request-class.html I might sooner or later implement this if no one beets me to it

    Why all this effort? Because suds uses urllib2 internally which is far inferior to python-requests as a HTTP client implementation.

    Yet one more edit: I made a gist available as a starting point https://gist.github.com/nanonyme/6268358 . It's MIT code and untested but should work as a starting point for the transport.

    0 讨论(0)
  • 2021-02-06 15:15

    In case anyone ends up reading this: suds-based solutions are mostly stagnated but there's a newer library called zeep written on top of requests and lxml. It is a completely separate solution and not a suds fork like these others. I know from personal experience that this is in use in some enterprise environments.

    0 讨论(0)
  • 2021-02-06 15:17

    I ran into the same problem recently, and unfortunately neither suds nor jurko-suds(a maintained fork of suds) were able to help. This is mainly because suds kept generating wrongly formatted soap envelope (this especially happens if the soap that is supposed to be generated has some content that's supposed to be inside a CDATA) different from what the server was expecting. This was the case even when I tried injecting the soap envelope myself using the __inject option.

    Here's how I solved it using python requests

    import requests
    
    request = u"""<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:req="http://SOME_URL">
       <soapenv:Header>
             <user>{0}</user>
             <pass>{1}</pass>
       </soapenv:Header>
       <soapenv:Body>
          <req:RequestInfo><![CDATA[<?xml version='1.0' encoding='UTF-8'?><request xmlns='http://SOME_OTHER_URL'>
        <Call>
            <callID>{2}</callID>
            ...
        </Call>
        <Foo>
            <Bar>
                <Baz>{3}</Baz>
                ...
            </Bar>
            <Neytri>
                ...
            </Neytri>
        </Foo>
        <Title>{4}</Title>
    </request>]]></req:RequestInfo>
       </soapenv:Body>
    </soapenv:Envelope>""".format('Jake_Sully', 
                                  'super_secret_pandora_password',
                                  'TYSGW-Wwhw',
                                  'something_cool',
                                  'SalaryPayment',
                                  'Pandora_title',
                                )
    
    encoded_request = request.encode('utf-8')
    
    headers = {"Host": "http://SOME_URL",
                "Content-Type": "application/soap+xml; charset=UTF-8",
                "Content-Length": str(len(encoded_request)),
                "SOAPAction": "http://SOME_OTHER_URL"}
    
    response = requests.post(url="http://SOME_OTHER_URL",
                         headers = headers,
                         data = encoded_request,
                         verify=False)
    
    print response.content #print response.text
    

    What was really important was to specify the Content-Type in the headers and also the SOAPAction. According to the SOAP 1.1 specifiaction

     The SOAPAction HTTP request header field can be used to indicate the intent of the SOAP HTTP request. The value is a URI identifying the intent. SOAP places no restrictions on the format or specificity of the URI or that it is resolvable. An HTTP client MUST use this header field when issuing a SOAP HTTP Request.       
    

    The value of SOAPAction can usually be found in the wsdl file of the API call that you want to make; if absent from the wsdl file then you can use an empty string as the value of that header

    Also see:

    1. http://archive.oreilly.com/pub/post/unraveling_the_mystery_of_soap.html
    2. http://www.prodigyproductionsllc.com/articles/programming/call-a-webservice-using-soap-and-python/
    0 讨论(0)
提交回复
热议问题