首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Python SimpleXMLRPCServer时无效的Unicode/XML?

使用Python SimpleXMLRPCServer时无效的Unicode/XML?
EN

Stack Overflow用户
提问于 2010-12-07 12:24:04
回答 3查看 4.3K关注 0票数 7

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

代码语言:javascript
复制
Fault: <Fault 1: "<class 'xml.parsers.expat.ExpatError'>:not well-formed (invalid token): line 6, column 15">

为什么?我必须修改SimpleXMLRPCServer库代码来修复这个问题吗?

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

代码语言:javascript
复制
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()

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

代码语言:javascript
复制
s = xmlrpclib.ServerProxy('http://localhost:9000')
s.tt(unichr(0x8))

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

代码语言:javascript
复制
liXXXXXX.members.linode.com - - [06/Dec/2010 23:19:40] "POST /RPC2 HTTP/1.0" 200 -

为什么服务器端没有错误?我如何诊断正在发生的事情?

我在客户端得到了以下回溯:

代码语言:javascript
复制
/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">

如果输入包含无效的XML,如何进行合理的服务器端处理?我可以清理这个数据服务器端吗?多么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-12-07 15:58:34

首先,你的例子对我也不起作用。我不知道您在问什么“如果输入包含无效的XML,服务器端处理是合理的”--您向服务器发送无效的XML,它会返回一个错误...你还想要什么?

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

代码语言:javascript
复制
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>

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

现在根据the XML-RPC spec的说法

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

字符串中允许除<和&之外的任何字符,这两个字符编码为<和&。字符串可用于编码二进制数据。

好的,但这是XML,根据XML spec

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

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

这不包括0x08,而且似乎完全与XML-RPC规范相矛盾!因此,它将看到XML规范是由您的XML解析器严格实现的(从错误判断,它看起来像是expat)。因为XML不允许0x08,所以您不能发送0x08,实际上,您会得到一个错误。

如果我们这样做了:

代码语言:javascript
复制
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)

...we获取您的错误。同样,您正在向服务器传递垃圾XML,服务器向您传回错误消息,中间的Python将该错误作为异常呈现给您。您期望的行为是什么?

票数 3
EN

Stack Overflow用户

发布于 2011-01-14 06:14:30

您在您的评论中指出,您希望为客户端处理尽可能多的XML。虽然乍一看这听起来不错(?),但也有一些缺点需要考虑:

  • 你怎么知道你能剥离什么?也许你你剥离了一些本来是重要的,但客户端发送了错误的代码,等等。
  • 想象一下,最初你支持一个特定的畸形请求。但是然后用户开始向你发送第二种类型的畸形,你也为那个类型添加了异常(一旦你为第一种添加了,为什么不呢?)。这是一条很长的路要走……
  • 最好让事情尽快失败,让它们在应该出现的地方得到处理。这一次客户端实现是错误的,所以让客户端通过修复它。从长远来看,对你们两个都更好。

如果您也管理客户端代码,那么您可能不得不在其上添加一些XML代码(例如,请参阅BeautifulSoup )。而是通过首先禁用无效输入来处理问题。

票数 0
EN

Stack Overflow用户

发布于 2012-05-25 16:19:07

塔纳托斯在他的post中完美地解释了你的问题的原因。

至于解决此问题的解决方案:您可以使用xmlrpclib.Binary对要发送的数据进行base64编码。(对于PY3K:xmlrpc.client.Binary)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4373369

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档