Недействительный Unicode / XML с Python SimpleXMLRPCServer? - PullRequest
7 голосов
/ 07 декабря 2010

Я получаю следующую ошибку на стороне клиента, когда передаю недопустимые символы 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 -

Почему нет ошибки на стороне сервера?Как мне диагностировать происходящее?

И я получаю следующую трассировку на стороне клиента:

/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 ]

3 голосов
/ 07 декабря 2010

Во-первых, ваш пример тоже не работает для меня. Я не знаю, что вы спрашиваете о "нормальной обработке на стороне сервера, если вход содержит недопустимый XML" - вы отправляете на сервер недопустимый XML, и он возвращает вам ошибку ... что еще вы хотите?

Во-вторых, введите 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>

Итак, вы видите сообщение об ошибке.

Теперь, согласно спецификации XML-RPC ,

  • Какие символы допускаются в строках? Непечатные символы? Нулевые персонажи? Можно ли использовать «строку» для хранения произвольного фрагмента двоичных данных?

В строке допускаются любые символы, кроме <и &, которые кодируются как & lt; и & amp ;. Строка может использоваться для кодирования двоичных данных. </p>

Хорошо, но это XML, и согласно спецификации XML :

Юридическими символами являются табуляция, возврат каретки, перевод строки и юридические символы Unicode и ISO / IEC 10646.

Char :: = # 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)

... мы получили вашу ошибку. Опять же, вы передаете мусорный XML на сервер, сервер возвращает вам сообщение об ошибке, и Python в середине представляет эту ошибку вам как исключение. Какое поведение вы ожидали?

0 голосов
/ 25 мая 2012

Танатос прекрасно объяснил причину вашей проблемы в своем сообщении .

Что касается решения этой проблемы: вы можете использовать xmlrpclib.Binary для base64-кодировать данные для отправки.(Для PY3K: xmlrpc.client.Binary )

0 голосов
/ 14 января 2011

Вы указали в своем комментарии, что хотели бы обработать как можно больше XML для клиента.Хотя это может показаться хорошим на первый взгляд (?), Есть минусы, которые следует учитывать:

  • Как узнать, что можно раздеть?Может быть, вы отбрасываете что-то, что было бы важно , но клиент отправляет это плохо закодировано и т. Д.

  • Представьте, что изначально вы поддерживаете запрос с одной конкретной ошибкой.Но затем пользователи начинают отправлять вам пороки второго типа, и вы добавляете исключение и для этого (если вы добавили для первого, почему бы и нет?).Это долгий путь вниз по дороге ...

  • Лучше позволить вещам провалиться как можно скорее и дать им возможность разобраться, где это должно быть.На этот раз реализация клиента неверна, поэтому пусть клиент исправит это .Лучше для вас обоих в долгосрочной перспективе.

Если вы также управляете клиентским кодом, тогда вы можете прибегнуть к использованию некоторой XML-кода (см. BeautifulSoup *).1022 * например).Но лучше справиться с проблемой, отключив неверный ввод.

...