简体   繁体   English

将python与suds用于sharepoint时的错误请求

[英]bad request when using python with suds for sharepoint

I am using Suds to access Sharepoint lists through soap, but I am having some trouble with malformed soap. 我正在使用Suds通过soap访问Sharepoint列表,但我在使用格式错误的肥皂时遇到了一些麻烦。

I am using the following code: 我使用以下代码:

from suds.client import Client
from suds.sax.element import Element
from suds.sax.attribute import Attribute
from suds.transport.https import WindowsHttpAuthenticated

import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)

ntlm = WindowsHttpAuthenticated(username='somedomain\\username', password='password')
url = "http://somedomain/sites/somesite/someothersite/somethirdsite/_vti_bin/Lists.asmx?WSDL"

client = Client(url, transport=ntlm)

result = client.service.GetListCollection()
print repr(result)

Every time I run this, I get the result Error 400 Bad request. 每次我运行它,我得到结果Error 400 Bad request。 As I have debugging enabled I can see the resulting envelope: 当我启用调试时,我可以看到生成的信封:

<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.microsoft.com/sharepoint/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <ns0:Body>
      <ns1:GetListCollection/>
   </ns0:Body>
</SOAP-ENV:Envelope>

...with this error message: ...出现此错误消息:

DEBUG:suds.client:http failed:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request</h2>
<hr><p>HTTP Error 400. The request is badly formed.</p>
</BODY></HTML>

Running the same WSDL (and raw envelope data as well) through SoapUI the request returns with values as expected. 通过SoapUI运行相同的WSDL(以及原始包络数据),请求将按预期返回值。 Can anyone see any obvious reason why I get the different results with Suds as SoapUI and how I can correct this? 任何人都可以看到任何明显的原因,为什么我得到不同的结果与Suds作为SoapUI以及我如何纠正这个?

UPDATE: after testing the exact same code on a different Sharepoint site (ie not a subsubsubsite with whitespace in its name) and with Java (JAX-WS, which also had issues with the same site, though, different issues) it appears as if it works as expected. 更新:在不同的Sharepoint站点上测试完全相同的代码(即不是名称中有空格的子子站点)和Java(JAX-WS,但同样的站点也存在问题,但是,不同的问题)看起来好像它按预期工作。 As a result I wonder if one of two details may be the reason for these problems: 结果我想知道这两个问题中的一个是否可能是造成这些问题的原因:

  • SOAP implementations have some issues with subsubsubsites in Sharepoint? SOAP实现在Sharepoint中的subsubsubsites有一些问题吗?
  • SOAP implementations have some issues with whitespace in its name, even if using %20 as a replacement? SOAP实现在名称中有一些空白问题,即使使用%20作为替代?

I still have the need to use the original URL with those issues, so any input would be highly appreciated. 我仍然需要将原始URL与这些问题一起使用,因此任何输入都将受到高度赞赏。 I assume that since SoapUI worked with the original url, it should be possible to correct whatever is wrong. 我假设因为SoapUI使用原始URL,所以应该可以纠正任何错误。

I think I narrowed down the issue, and it is specific to suds (possibly other SOAP implementations as well). 我认为我缩小了问题范围,它特定于suds(可能还有其他SOAP实现)。 Your bullet point: 你的要点:

  • SOAP implementations have some issues with whitespace in its name, even if using %20 as a replacement? SOAP实现在名称中有一些空白问题,即使使用%20作为替代?

That's spot on. 那就是现场。 Turning up debug logging for suds allowed me to grab the endpoint, envelope, and headers. 打开suds的调试日志记录使我能够获取端点,信封和标题。 Mimicking the exact same call using cURL returns a valid response, but suds it throws the bad request. 使用cURL模仿完全相同的调用会返回一个有效的响应,但suds会抛出错误的请求。

The issue is that suds takes your WSDL (url parameter) and parses it, but it doesn't include the URL encoded string. 问题是suds接受你的WSDL(url参数)并解析它,但它不包括URL编码的字符串。 This leads to debug messages like this: 这导致调试消息如下:

DEBUG:suds.transport.http:opening (https://sub.site.com/sites/Site Collection with Spaces/_vti_bin/UserGroup.asmx?WSDL)
<snip>
TransportError: HTTP Error 400: Bad Request

Piping this request through a fiddler proxy showed that it was running the request against the URL https://sub.site.com/sites/Site due to the way it parses the WSDL. 通过fiddler代理管理此请求表明它正在运行针对URL https://sub.site.com/sites/Site的请求,因为它解析了WSDL。 The issue is that you aren't passing the location parameter to suds.client.Client. 问题是您没有将location参数传递给suds.client.Client。 The following code gives me valid responses every time: 以下代码每次都给我有效的回复:

from ntlm3 import ntlm
from suds.client import Client
from suds.transport.https import WindowsHttpAuthenticated

# URL without ?WSDL
url = 'https://sub.site.com/sites/Site%20Collection%20with%20Spaces/_vti_bin/Lists.asmx'

# Create NTLM transport handler
transport = WindowsHttpAuthenticated(username='foo',
                                     password='bar')
# We use FBA, so this forces it to challenge us with 
# a 401 so WindowsHttpAuthenticated can take over.
msg = ("%s\\%s" % ('DOM', 'foo'))
auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(msg).decode('ascii')
# Create the client and append ?WSDL to the URL.
client = Client(url=(url + "?WSDL"),
                location=url,
                transport=transport)
# Add the NTLM header to force negotiation.
header = {'Authorization': auth}
client.set_options(headers=header)

One caveat: Using quote from urllib works, but you cannot encode the entire URL or it fails to recognize the URL. 一个警告:使用urllib quote可以工作,但是您无法对整个URL进行编码,或者无法识别URL。 You are better off just doing a replace on spaces with %20. 你最好只用%20替换空格。

url = url.replace(' ','%20')

Hope this keeps someone else from banging their head against the wall. 希望这可以防止别人撞到墙上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM