如何为 suds soap 客户端正确设置 headers

How to set headers properly for suds soap client

我正在尝试使用 suds 客户端向 api 发送请求。

请求的格式如下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v20="https://API">
   <soapenv:Header>
      <v20:apiHeader>
         <v20:username>username</v20:username>
         <v20:password>password</v20:password>
         <!--Optional:-->
         <v20:name>?</v20:name>
      </v20:apiHeader>
   </soapenv:Header>
   <soapenv:Body>
      <v20:getLoginDetails/>
   </soapenv:Body>
</soapenv:Envelope>

我正在发送这样的请求:

client = Client('https://wsdl', faults=False)

client.set_options(headers={'username': username 'authToken': auth_token, 'name': ''})
client.service.getLoginDetails()

我收到的错误是:

(<HTTPStatus.INTERNAL_SERVER_ERROR: 500>, (Fault){
   faultcode = "soap:Server"
   faultstring = "apiHeader should not be null"
   detail = ""
 })

这是我发送请求的方式吗?我认为这绝对与 apiHeader 有关;不确定是什么,我使用这个得到了同样的错误:

username = Element('username').setText(name)
        password= Element('password').setText(pass)
        header_list = [username, pass]
        self.client.set_options(soapheaders=header_list)
        return self.client.service.getLoginDetails()

我用类似这样的东西完成了这项工作:

from suds.sax.element import Element
from suds.sax.attribute import Attribute
code = Element('serviceCode').setText('PABB4BEIJING')
pwd = Element('servicePwd').setText('QWERTPABB')

reqsoapheader = Element('ReqSOAPHeader').insert(code)
reqsoap_attribute = Attribute('xmlns', "http://schemas.acme.eu/")
reqsoapheader.append(reqsoap_attribute)

client.set_options(soapheaders=reqsoapheader)

如果您希望向 SOAP 添加多个元素header:

userName = Element('UserName').setText(config['fco.user'])
password = Element('Password').setText(config['fco.pwd'])
fdxns = Attribute('xmlns', "http://fdx.co.il/Authentication")
for field in userName, password:
    field.append(fdxns)
soapheaders = [userName, password]
client.set_options(soapheaders=tuple(soapheaders))

这对我有用 Python 2.7,泡沫 0.4。

#您服务器的代码:

from spyne import Application, rpc, ServiceBase, Unicode
from spyne.model.complex import ComplexModel
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
import json


class RequestHeader(ComplexModel):
    user_name = Unicode
    user_pass = Unicode

class ServiceTest(ServiceBase):
    __in_header__ = RequestHeader
    
    @rpc(Unicode, _returns=Unicode)
    def getLoginDetails(ctx, request):
        values = json.loads(request)
        values['user_name'] = ctx.in_header.user_name
        values['user_pass'] = ctx.in_header.user_pass
        return json.dumps(values)

application = WsgiApplication(Application([ServiceTest],
    tns='yourcompany.request',
    in_protocol=Soap11(validator='lxml'),
    out_protocol=Soap11()
))

if __name__ == '__main__':
    from wsgiref.simple_server import make_server    
    server = make_server('0.0.0.0', 8000, application)
    server.serve_forever()

#您的客户代码:

import json
from suds.client import Client  

#Prepare the request in a JSON format
request = json.dumps({})

#Create a client for the API and make the request
api_client = Client('http://localhost:8000/?wsdl')
header = api_client.factory.create("RequestHeader")
header.user_name = 'my_user_name'
header.user_pass = 'my_user_pass'
api_client.set_options(soapheaders=header)
response = api_client.service.getLoginDetails(request)
print(response)

#it would print:
#{"user_name": "my_user_name", "user_pass": "my_user_pass"}