Skip to content

Commit b3af08f

Browse files
committed
Fix for issue5040. Adding support for unicode message passing and tests for unicode message and test for Content-Length.
1 parent df8709d commit b3af08f

File tree

3 files changed

+44
-13
lines changed

3 files changed

+44
-13
lines changed

Lib/test/test_xmlrpc.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import http.client
1010
import socket
1111
import os
12+
import re
1213
from test import support
1314

1415
alist = [{'astring': 'foo@bar.baz.spam',
@@ -352,6 +353,19 @@ def test_simple1(self):
352353
# protocol error; provide additional information in test output
353354
self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
354355

356+
def test_nonascii(self):
357+
start_string = 'P\N{LATIN SMALL LETTER Y WITH CIRCUMFLEX}t'
358+
end_string = 'h\N{LATIN SMALL LETTER O WITH HORN}n'
359+
try:
360+
p = xmlrpclib.ServerProxy(URL)
361+
self.assertEqual(p.add(start_string, end_string),
362+
start_string + end_string)
363+
except (xmlrpclib.ProtocolError, socket.error) as e:
364+
# ignore failures due to non-blocking socket 'unavailable' errors
365+
if not is_unavailable_exception(e):
366+
# protocol error; provide additional information in test output
367+
self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
368+
355369
# [ch] The test 404 is causing lots of false alarms.
356370
def XXXtest_404(self):
357371
# send POST with http.client, it should return 404 header and
@@ -616,9 +630,21 @@ def test_cgi_xmlrpc_response(self):
616630
# need only xml
617631
self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, handle[44:])
618632

633+
# Also test the content-length returned by handle_request
634+
# Using the same test method inorder to avoid all the datapassing
635+
# boilerplate code.
636+
# Test for bug: http://bugs.python.org/issue5040
637+
638+
content = handle[handle.find("<?xml"):]
639+
640+
self.assertEquals(
641+
int(re.search('Content-Length: (\d+)', handle).group(1)),
642+
len(content))
643+
619644
os.remove("xmldata.txt")
620645
os.remove(support.TESTFN)
621646

647+
622648
def test_main():
623649
xmlrpc_tests = [XMLRPCTestCase, HelperTestCase, DateTimeTestCase,
624650
BinaryTestCase, FaultTestCase]

Lib/xmlrpc/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,15 +1316,15 @@ def __init__(self, uri, transport=None, encoding=None, verbose=0,
13161316
transport = Transport(use_datetime=use_datetime)
13171317
self.__transport = transport
13181318

1319-
self.__encoding = encoding
1319+
self.__encoding = encoding or 'utf-8'
13201320
self.__verbose = verbose
13211321
self.__allow_none = allow_none
13221322

13231323
def __request(self, methodname, params):
13241324
# call a method on the remote server
13251325

13261326
request = dumps(params, methodname, encoding=self.__encoding,
1327-
allow_none=self.__allow_none)
1327+
allow_none=self.__allow_none).encode(self.__encoding)
13281328

13291329
response = self.__transport.request(
13301330
self.__host,

Lib/xmlrpc/server.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def __init__(self, allow_none, encoding):
163163
self.funcs = {}
164164
self.instance = None
165165
self.allow_none = allow_none
166-
self.encoding = encoding
166+
self.encoding = encoding or 'utf-8'
167167

168168
def register_instance(self, instance, allow_dotted_names=False):
169169
"""Registers an instance to respond to XML-RPC requests.
@@ -266,7 +266,7 @@ def _marshaled_dispatch(self, data, dispatch_method = None):
266266
encoding=self.encoding, allow_none=self.allow_none,
267267
)
268268

269-
return response
269+
return response.encode(self.encoding)
270270

271271
def system_listMethods(self):
272272
"""system.listMethods() => ['add', 'subtract', 'multiple']
@@ -473,8 +473,6 @@ def do_POST(self):
473473

474474
self.end_headers()
475475
else:
476-
# Got a valid XML RPC response; convert to bytes first
477-
response = response.encode("utf-8")
478476
self.send_response(200)
479477
self.send_header("Content-type", "text/xml")
480478
self.send_header("Content-length", str(len(response)))
@@ -551,7 +549,9 @@ def handle_xmlrpc(self, request_text):
551549
print('Content-Type: text/xml')
552550
print('Content-Length: %d' % len(response))
553551
print()
554-
sys.stdout.write(response)
552+
sys.stdout.flush()
553+
sys.stdout.buffer.write(response)
554+
sys.stdout.buffer.flush()
555555

556556
def handle_get(self):
557557
"""Handle a single HTTP GET request.
@@ -569,11 +569,14 @@ def handle_get(self):
569569
'message' : message,
570570
'explain' : explain
571571
}
572+
response = response.encode('utf-8')
572573
print('Status: %d %s' % (code, message))
573-
print('Content-Type: text/html')
574+
print('Content-Type: %s' % http.server.DEFAULT_ERROR_CONTENT_TYPE)
574575
print('Content-Length: %d' % len(response))
575576
print()
576-
sys.stdout.write(response)
577+
sys.stdout.flush()
578+
sys.stdout.buffer.write(response)
579+
sys.stdout.buffer.flush()
577580

578581
def handle_request(self, request_text = None):
579582
"""Handle a single XML-RPC request passed through a CGI post method.
@@ -814,12 +817,12 @@ def do_GET(self):
814817
self.report_404()
815818
return
816819

817-
response = self.server.generate_html_documentation()
820+
response = self.server.generate_html_documentation().encode('utf-8')
818821
self.send_response(200)
819822
self.send_header("Content-type", "text/html")
820823
self.send_header("Content-length", str(len(response)))
821824
self.end_headers()
822-
self.wfile.write(response.encode())
825+
self.wfile.write(response)
823826

824827
# shut down the connection
825828
self.wfile.flush()
@@ -852,12 +855,14 @@ def handle_get(self):
852855
documentation.
853856
"""
854857

855-
response = self.generate_html_documentation()
858+
response = self.generate_html_documentation().encode('utf-8')
856859

857860
print('Content-Type: text/html')
858861
print('Content-Length: %d' % len(response))
859862
print()
860-
sys.stdout.write(response)
863+
sys.stdout.flush()
864+
sys.stdout.buffer.write(response)
865+
sys.stdout.buffer.flush()
861866

862867
def __init__(self):
863868
CGIXMLRPCRequestHandler.__init__(self)

0 commit comments

Comments
 (0)