你能帮我解决这个 SUDS/SOAP 问题吗?

发布于 2024-08-24 18:28:07 字数 2196 浏览 7 评论 0原文

所以我试图访问这个api https://www.clarityaccounting.com/api-docs/ 使用 SUDS。这是应该工作的代码:

from suds.client import Client
client = Client('https://www.clarityaccounting.com/api/v1?wsdl')
token = client.service.doLogin('demo', 'demo', 'www.kashoo.com', 'en_US', 300000)

但我收到此错误:

WebFault: Server raised fault: 'No such operation:  (HTTP GET PATH_INFO: /api/v1)'

他们的支持人员说请求应该如下所示:

<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:api="http://api.service.books/">
  <SOAP-ENV:Body>
     <api:doLogin>
        <username>demo</username>
        <password>demo</password>
        <siteName>www.kashoo.com</siteName>
        <locale>en_US</locale>
        <duration>300000</duration>
     </api:doLogin>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

但 SUDS 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope 
xmlns:ns0="http://api.service.books/" 
xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <ns1:Body>
      <ns0:doLogin>
         <username>demo</username>
         <password>demo</password>
         <siteName>www.kashoo.com</siteName>
         <locale>en_US</locale>
         <duration>300000</duration>
      </ns0:doLogin>
   </ns1:Body>
</SOAP-ENV:Envelope>

我是一个真正的 SOAP 和 SUDS 新手,但我听说 SUDS 是最好的从这里使用的 SOAP 库: Python 存在哪些 SOAP 客户端库,它们的文档在哪里?

所以我的问题是简单地说,有哪些不同的关键部分导致请求失败,以及如何配置 SUDS 来发送格式正确的请求?

So I'm trying to access this api https://www.clarityaccounting.com/api-docs/ using SUDS. Here is the code that should work:

from suds.client import Client
client = Client('https://www.clarityaccounting.com/api/v1?wsdl')
token = client.service.doLogin('demo', 'demo', 'www.kashoo.com', 'en_US', 300000)

But I get this error:

WebFault: Server raised fault: 'No such operation:  (HTTP GET PATH_INFO: /api/v1)'

Their support guy says that the request should look like this:

<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:api="http://api.service.books/">
  <SOAP-ENV:Body>
     <api:doLogin>
        <username>demo</username>
        <password>demo</password>
        <siteName>www.kashoo.com</siteName>
        <locale>en_US</locale>
        <duration>300000</duration>
     </api:doLogin>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

But SUDS' looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope 
xmlns:ns0="http://api.service.books/" 
xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <ns1:Body>
      <ns0:doLogin>
         <username>demo</username>
         <password>demo</password>
         <siteName>www.kashoo.com</siteName>
         <locale>en_US</locale>
         <duration>300000</duration>
      </ns0:doLogin>
   </ns1:Body>
</SOAP-ENV:Envelope>

I'm a real SOAP and SUDS newbie but I heard that SUDS is the best SOAP library to use from here: What SOAP client libraries exist for Python, and where is the documentation for them?

So my question is simply what are the crucial parts that are different and that are making the request fail and how can I configure SUDS to send the properly formatted request?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浮华 2024-08-31 18:28:07

乍一看,您遇到的问题似乎出在 SSL 上。您正在访问 https URL,并且 suds.client 的传输处理程序默认使用 http。

问题
如果您查看 WSDL 的底部,它会将默认位置指定为 http://www.clarityaccounting.com/api/v1,这是一个 http URL,但 WSDL 是 SSL。

 <wsdl:service name="v1">
    <wsdl:port binding="tns:v1SoapBinding" name="BooksApiV1Port">
      <soap:address location="http://www.clarityaccounting.com/api/v1"/>
    </wsdl:port>
 </wsdl:service>

如果您对该 URL 执行 http GET,您会收到收到的错误消息:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Server</faultcode>
            <faultstring>No such operation:  (HTTP GET PATH_INFO: /api/v1)</faultstring>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

解决方案
要解决此问题,您需要在调用 Client 构造函数时覆盖默认位置,以使其与 https:

>>> url
'https://www.clarityaccounting.com/api/v1?wsdl'
>>> client = Client(url, location='https://www.clarityaccounting.com/api/v1')
>>> token = client.service.doLogin('demo', 'demo', 'www.kashoo.com', 'en_US', 300000)
>>> token
(authToken){
   authenticationCode = "ObaicdMJZY6UM8xZ2wzGjicT0jQ="
   expiryDate = 2010-03-05 12:31:41.000698
   locale = "en_US"
   myUserId = 4163
   site = "www.kashoo.com"
 }

Victory! 保持一致

,以供将来调试之用的专业提示:打开完整日志记录调试。 SUDS 使用标准logging 库,因此它为您提供了很多控制权。所以我把它全部调高到DEBUG

import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
logging.getLogger('suds.transport').setLevel(logging.DEBUG)
logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
logging.getLogger('suds.wsdl').setLevel(logging.DEBUG)

这帮助我缩小了范围,因为它清楚地表明它是通过http发送的:

DEBUG:suds.transport.http:sending:
URL:http://www.clarityaccounting.com/api/v1
(xml output omitted)

然后响应也这么说:

DEBUG:suds.client:http failed:

At first glance looks like the problem you're having is with SSL. You are accessing an https URL, and the Transport handler for suds.client talks http by default.

The problem
If you look at the bottom of the WSDL it is specifying the default location as http://www.clarityaccounting.com/api/v1, which is an http URL, but the WSDL is SSL.

 <wsdl:service name="v1">
    <wsdl:port binding="tns:v1SoapBinding" name="BooksApiV1Port">
      <soap:address location="http://www.clarityaccounting.com/api/v1"/>
    </wsdl:port>
 </wsdl:service>

If you do an http GET on that URL, you get the error message you received:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Server</faultcode>
            <faultstring>No such operation:  (HTTP GET PATH_INFO: /api/v1)</faultstring>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

The Solution
To fix this you need to override the default location when you call the Client constructor to make it stick with https:

>>> url
'https://www.clarityaccounting.com/api/v1?wsdl'
>>> client = Client(url, location='https://www.clarityaccounting.com/api/v1')
>>> token = client.service.doLogin('demo', 'demo', 'www.kashoo.com', 'en_US', 300000)
>>> token
(authToken){
   authenticationCode = "ObaicdMJZY6UM8xZ2wzGjicT0jQ="
   expiryDate = 2010-03-05 12:31:41.000698
   locale = "en_US"
   myUserId = 4163
   site = "www.kashoo.com"
 }

Victory!

Pro tip for future debugging purposes: Turn on full logging debugging. SUDS uses the standard logging library, so it gives you a lot of control. So I cranked it all up to DEBUG:

import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
logging.getLogger('suds.transport').setLevel(logging.DEBUG)
logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
logging.getLogger('suds.wsdl').setLevel(logging.DEBUG)

This is what helped me narrow it down, because it was clearly saying it was sending over http:

DEBUG:suds.transport.http:sending:
URL:http://www.clarityaccounting.com/api/v1
(xml output omitted)

And then the response said so as well:

DEBUG:suds.client:http failed:
岁月染过的梦 2024-08-31 18:28:07

使用suds-jurko https://pypi.python.org/pypi/suds-jurko这是一个维护的泡沫叉子。
您可以传入 __inject 选项,您可以在其中为其提供要发送的原始 xml。

from suds.client import Client

username, password, sitename, locale, duration = 'demo', 'demo', 'www.kashoo.com', 'en_US', 300000

raw_xml = """<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:api="http://api.service.books/">
  <SOAP-ENV:Body>
     <api:doLogin>
        <username>{0}</username>
        <password>{1}</password>
        <siteName>{2}</siteName>
        <locale>{3}</locale>
        <duration>{4}</duration>
     </api:doLogin>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>""".format(username, password, sitename, locale, duration)

client = Client(url, location)
result = client.service.doLogin(__inject={'msg':raw_xml})

我觉得我应该记录人们可以在这里检查泡沫产生的生肥皂的所有方法。

  1. 构建客户端时使用 nosend 标志。请注意,当该标志设置为 True 时,suds 将仅生成肥皂,但不会发送它。

    client =Client(url, nosend=True)
    res = client.service.example()
    print res.envelope #打印原始肥皂

  2. 使用日志记录。这里我们只记录 suds.transport.http,因此它只会输出发送/接收的内容。

    导入日志记录
    导入系统
    handler =logging.StreamHandler(sys.stderr)
    logger =logging.getLogger('suds.transport.http')
    logger.setLevel(logging.DEBUG), handler.setLevel(logging.DEBUG)
    logger.addHandler(handler)

  3. 使用 MessagePlugin

    从 suds.plugin 导入 MessagePlugin
    类MyPlugin(MessagePlugin):
    def marshalled(self, context):
    #导入pdb; pdb.set_trace()
    打印 context.envelope.str()

    client = Client(url, plugins=[MyPlugin()])

MessagePlugin 不仅使您能够检查生成的肥皂但您也可以在发送前修改它,请参阅-> https://jortel.fedorapeople.org/suds/doc/suds .plugin.MessagePlugin-class.html

Using suds-jurko https://pypi.python.org/pypi/suds-jurko which is a maintained fork of suds.
You can pass in an __inject option where you can give it the raw xml you want to send.

from suds.client import Client

username, password, sitename, locale, duration = 'demo', 'demo', 'www.kashoo.com', 'en_US', 300000

raw_xml = """<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:api="http://api.service.books/">
  <SOAP-ENV:Body>
     <api:doLogin>
        <username>{0}</username>
        <password>{1}</password>
        <siteName>{2}</siteName>
        <locale>{3}</locale>
        <duration>{4}</duration>
     </api:doLogin>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>""".format(username, password, sitename, locale, duration)

client = Client(url, location)
result = client.service.doLogin(__inject={'msg':raw_xml})

I feel like I should document all the ways that one can inspect the Raw soap that suds generates here.

  1. Using a nosend flag when constructing the client. Please note that with the flag set to True, suds will just generate the soap but not send it.

    client =Client(url, nosend=True)
    res = client.service.example()
    print res.envelope #prints the raw soap

  2. Using logging. Here we are only logging suds.transport.http, so it will only output whatever is sent/received.

    import logging
    import sys
    handler = logging.StreamHandler(sys.stderr)
    logger = logging.getLogger('suds.transport.http')
    logger.setLevel(logging.DEBUG), handler.setLevel(logging.DEBUG)
    logger.addHandler(handler)

  3. Using the MessagePlugin

    from suds.plugin import MessagePlugin
    class MyPlugin(MessagePlugin):
    def marshalled(self, context):
    #import pdb; pdb.set_trace()
    print context.envelope.str()

    client = Client(url, plugins=[MyPlugin()])

Not only does the MessagePlugin give you the ability to inspect the soap generated but you can also modify it before sending, see-> https://jortel.fedorapeople.org/suds/doc/suds.plugin.MessagePlugin-class.html

无言温柔 2024-08-31 18:28:07

这不应该是与通过 HTTPS 连接到服务相关的问题。我正在使用泡沫来做同样的事情。我尝试了几种处理您的 WSDL 文件的方法(我自己不是专家),但遇到了相同的错误。不过,作为使用 suds 的练习,您应该使用 factory 方法,例如

login = client.factory.create('doLogin')
login.username = 'username'
etc...

发送到 create 函数的任何内容都是 WSDL 文件中定义的类型之一。如果您在 shell 中创建该类型,则可以运行“打印登录”来查看其附加属性。

希望这至少能告诉您问题所在(使用 HTTPS)。另外,我注意到 WSDL 文件中未设置soapAction 标头,不确定suds 或服务如何在没有该标头的情况下处理请求。

It shouldn't be a problem related to connecting to a service over HTTPS. I'm using suds to do the same thing. I've tried a few approaches to your WSDL file (not an expert myself) and encountered the same error. What you should do as practice with suds though is use the factory method, e.g.

login = client.factory.create('doLogin')
login.username = 'username'
etc...

Where anything sent to the create function is one of the types defined in the WSDL file. If you create that type in the shell you can run 'print login' to see its additional properties.

Hope this at least tells you where the problem isn't (with HTTPS). Also, I noticed that the soapAction headers aren't set in the WSDL file, not sure how suds or the service handles requests without that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文