Недопустимый Unicode / XML с Python SimpleXMLRPCServer?
я получаю следующую ошибку на стороне клиента, когда я передаю недопустимые символы XML на Python SimpleXMLRPCServer:
Fault: <Fault 1: "<class 'xml.parsers.expat.ExpatError'>:not well-formed (invalid token): line 6, column 15">
почему? Должен ли я изменить код библиотеки 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()
вот мой код клиента XML-RPC:
s = xmlrpclib.ServerProxy('http://localhost:9000')
s.tt(unichr(0x8))
на стороне сервера я не получаю никаких ошибок или трассировки:
liXXXXXX.members.linode.com - - [06/Dec/2010 23:19:40] "POST /RPC2 HTTP/1.0" 200 -
почему нет ошибки на стороне сервера? Как я диагностировать, что происходит?
и я получаю следующий traceback на стороне клиента:
/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? Могу ли я очистить эту сторону сервера данных? Как?
3 ответов
во-первых, ваш пример не работает для меня, либо. Я не знаю, что вы спрашиваете о "нормальной обработке на стороне сервера, если вход содержит недопустимый XML" - вы отправляете недопустимый XML-код сервера, и он возвращает вам ошибку... чего ты еще хочешь?
во-вторых, stick a print 'hi there'
на tt
, вы увидите, что tt
не вызывается, когда вы отправляете unichr(0x8)
. Точный ответ (a 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><class 'xml.parsers.expat.ExpatError'>:not well-formed (invalid token): line 6, column 15</string></value>
</member>
</struct></value>
</fault>
</methodResponse>
Итак, вы видите свои ошибки сообщение.
теперь, согласно спецификация XML-RPC,
- какие символы разрешены в строках? Непечатаемые символы? Нулевые символы? Можно ли использовать" строку " для хранения произвольного куска двоичных данных?
любые символы в строке, Кроме
Ok, но это XML, и в соответствии с XML spec:
юридические символы-это вкладка, возврат каретки, подача строки и юридические символы Unicode и ISO/IEC 10646.
Char :: = #x9 / #xA / #xD / [#x20 - #xD7FF] / [#xE000 - #xFFFD] / [#x10000 - #x10FFFF]
который не включает 0x08 и, похоже, полностью противоречит спецификации XML-RPC! Таким образом, он увидит, что спецификация XML реализуется довольно строго вашим синтаксическим анализатором XML (который, судя по ошибка, похоже, expat). Поскольку 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)
...мы понимаем вашу ошибку. Опять же, вы передаете XML мусора на сервер, сервер передает вам сообщение об ошибке, а Python в середине представляет эту ошибку вам как исключение. Какого поведения вы ожидали?
Вы указали в своем комментарии, что хотели бы обработать как можно больше XML для клиента. Хотя это может звучать хорошо на первый взгляд (?), есть минусы, чтобы рассмотреть:
Как вы знаете, что вы можете раздеться? Может быть!--5-->ты сбросишь то, что было бы важно, но клиент отправляет его плохо закодированным и т. д.
представьте, что изначально вы поддерживаете запрос с одной конкретной аномалией. Зато пользователи начинают отправлять вам мальформацию второго типа, и вы добавляете исключение для этого тоже (после добавления для первого, почему бы и нет?). Это долгий путь вниз по дороге...
лучше позволить вещам потерпеть неудачу как можно скорее, и пусть с ними разбираются там, где это должно быть. На этот раз реализация клиента неверна, поэтому пусть клиент исправит это. Так будет лучше для вас обоих.
Если вы управляете кодом клиента также, тогда вы можете в последнюю очередь прибегнуть к нажатию некоторого XML tidy на нем (см. BeautifulSoup например). Но вместо этого решите проблему, отключив неверный ввод в первую очередь.
Танатос прекрасно объяснил причину вашей проблемы в своем в должности.
Что касается решения этой проблемы: вы можете использовать xmlrpclib.Двоичный to base64-кодировать отправляемые данные. (Для PY3K: файла xmlrpc.клиент.Двоичный)