使用Python SimpleXMLRPCServer的无效Unicode/XML?

Jos*_*ian 7 python unicode xml-rpc simplexmlrpcserver

当我将无效的XML字符传递给Python SimpleXMLRPCServer时,我在客户端获得以下错误:

Fault: <Fault 1: "<class 'xml.parsers.expat.ExpatError'>:not well-formed (invalid token): line 6, column 15">
Run Code Online (Sandbox Code Playgroud)

为什么?我是否必须更改SimpleXMLRPCServer库代码才能解决此问题?

这是我的XML-RPC服务器代码:

from SimpleXMLRPCServer import SimpleXMLRPCServer

import logging
logging.basicConfig(level=logging.DEBUG)

def tt(text):
    return "cool"

server = SimpleXMLRPCServer(("0.0.0.0", 9000))
server.register_introspection_functions()
server.register_function(tt)

# Run the server's main loop
server.serve_forever()
Run Code Online (Sandbox Code Playgroud)

这是我的XML-RPC客户端代码:

s = xmlrpclib.ServerProxy('http://localhost:9000')
s.tt(unichr(0x8))
Run Code Online (Sandbox Code Playgroud)

在服务器端,我没有得到任何错误或回溯:

liXXXXXX.members.linode.com - - [06/Dec/2010 23:19:40] "POST /RPC2 HTTP/1.0" 200 -
Run Code Online (Sandbox Code Playgroud)

为什么服务器端没有错误?我如何诊断发生了什么?

我在客户端获得以下回溯:

/usr/lib/python2.6/xmlrpclib.pyc in __call__(self, *args)
   1197         return _Method(self.__send, "%s.%s" % (self.__name, name))
   1198     def __call__(self, *args):
-> 1199         return self.__send(self.__name, args)
   1200 
   1201 ##


/usr/lib/python2.6/xmlrpclib.pyc in __request(self, methodname, params)
   1487             self.__handler,
   1488             request,
-> 1489             verbose=self.__verbose
   1490             )
   1491 

/usr/lib/python2.6/xmlrpclib.pyc in request(self, host, handler, request_body, verbose)
   1251             sock = None
   1252 
-> 1253         return self._parse_response(h.getfile(), sock)
   1254 
   1255     ##


/usr/lib/python2.6/xmlrpclib.pyc in _parse_response(self, file, sock)
   1390         p.close()
   1391 
-> 1392         return u.close()
   1393 
   1394 ##


/usr/lib/python2.6/xmlrpclib.pyc in close(self)
    836             raise ResponseError()
    837         if self._type == "fault":
--> 838             raise Fault(**self._stack[0])
    839         return tuple(self._stack)
    840 

Fault: <Fault 1: "<class 'xml.parsers.expat.ExpatError'>:not well-formed (invalid token): line 6, column 15">
Run Code Online (Sandbox Code Playgroud)

如果输入包含无效的XML,如何获得理智的服务器端处理?我可以清理这个数据服务器端吗?怎么样?

Tha*_*tos 3

首先,你的例子也不适合我。我不知道你在问“如果输入包含无效的 XML,则进行正常的服务器端处理”——你向服务器发送了无效的 XML,它给你返回了一个错误......你还想要什么?

其次,粘贴 a print 'hi there'tt您将看到tt发送时没有被调用unichr(0x8)。服务器的确切响应(200)是:

HTTP/1.0 200 OK
Server: BaseHTTP/0.3 Python/2.6.5
Date: Tue, 07 Dec 2010 07:33:09 GMT
Content-type: text/xml
Content-length: 350

<?xml version='1.0'?>
<methodResponse>
<fault>
<value><struct>
<member>
<name>faultCode</name>
<value><int>1</int></value>
</member>
<member>
<name>faultString</name>
<value><string>&lt;class 'xml.parsers.expat.ExpatError'&gt;:not well-formed (invalid token): line 6, column 15</string></value>
</member>
</struct></value>
</fault>
</methodResponse>
Run Code Online (Sandbox Code Playgroud)

因此,您会看到错误消息。

现在,根据XML-RPC 规范

  • 字符串中允许使用哪些字符?不可打印的字符?空字符?“字符串”可以用来保存任意的二进制数据块吗?

字符串中允许使用除 < 和 & 之外的任何字符,它们被编码为 < 和 < 和&。字符串可用于对二进制数据进行编码。

好的,但这是 XML,并且根据XML 规范

合法字符包括制表符、回车符、换行符以及 Unicode 和 ISO/IEC 10646 的合法字符。

字符 ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]

其中不包括 0x08,并且似乎完全违背 XML-RPC 规范!因此,它会看到您的 XML 解析器相当严格地实现了 XML 规范(从错误来看,它看起来是外籍的)。由于 XML 不允许 0x08,因此您无法发送 0x08,实际上,您会收到错误。

如果我们这样做:

data = "<?xml version='1.0'?>\n<methodCall>\n<methodName>tt</methodName>\n<params>\n<param>\n<value><string>\x08</string></value>\n</param>\n</params>\n</methodCall>"
p = xml.parsers.expat.ParserCreate()
p.Parse(data, True)
Run Code Online (Sandbox Code Playgroud)

...我们收到您的错误。同样,您将垃圾 XML 传递给服务器,服务器向您传回一条错误消息,而中间的 Python 则将该错误作为异常呈现给您。您期望什么行为?