summaryrefslogtreecommitdiffstats
path: root/Lib/SimpleXMLRPCServer.py
diff options
context:
space:
mode:
authorKristján Valur Jónsson <kristjan@ccpgames.com>2009-06-28 21:04:17 (GMT)
committerKristján Valur Jónsson <kristjan@ccpgames.com>2009-06-28 21:04:17 (GMT)
commite007860b8b3609ce0bc62b1780efaa06241520bd (patch)
tree687961d29bff1d936ed949cf591bbe8285d9e54d /Lib/SimpleXMLRPCServer.py
parent552e7a7e2f526fa0637a3e14f47354c567dfe26e (diff)
downloadcpython-e007860b8b3609ce0bc62b1780efaa06241520bd.zip
cpython-e007860b8b3609ce0bc62b1780efaa06241520bd.tar.gz
cpython-e007860b8b3609ce0bc62b1780efaa06241520bd.tar.bz2
http://bugs.python.org/issue6267
Cumulative patch to http and xmlrpc
Diffstat (limited to 'Lib/SimpleXMLRPCServer.py')
-rw-r--r--Lib/SimpleXMLRPCServer.py57
1 files changed, 51 insertions, 6 deletions
diff --git a/Lib/SimpleXMLRPCServer.py b/Lib/SimpleXMLRPCServer.py
index 967ac7e..5b5aced 100644
--- a/Lib/SimpleXMLRPCServer.py
+++ b/Lib/SimpleXMLRPCServer.py
@@ -106,6 +106,7 @@ import BaseHTTPServer
import sys
import os
import traceback
+import re
try:
import fcntl
except ImportError:
@@ -430,6 +431,31 @@ class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
# paths not on this list will result in a 404 error.
rpc_paths = ('/', '/RPC2')
+ #if not None, encode responses larger than this, if possible
+ encode_threshold = 1400 #a common MTU
+
+ #Override form StreamRequestHandler: full buffering of output
+ #and no Nagle.
+ wbufsize = -1
+ disable_nagle_algorithm = True
+
+ # a re to match a gzip Accept-Encoding
+ aepattern = re.compile(r"""
+ \s* ([^\s;]+) \s* #content-coding
+ (;\s* q \s*=\s* ([0-9\.]+))? #q
+ """, re.VERBOSE | re.IGNORECASE)
+
+ def accept_encodings(self):
+ r = {}
+ ae = self.headers.get("Accept-Encoding", "")
+ for e in ae.split(","):
+ match = self.aepattern.match(e)
+ if match:
+ v = match.group(3)
+ v = float(v) if v else 1.0
+ r[match.group(1)] = v
+ return r
+
def is_rpc_path_valid(self):
if self.rpc_paths:
return self.path in self.rpc_paths
@@ -463,6 +489,10 @@ class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
size_remaining -= len(L[-1])
data = ''.join(L)
+ data = self.decode_request_content(data)
+ if data is None:
+ return #response has been sent
+
# In previous versions of SimpleXMLRPCServer, _dispatch
# could be overridden in this class, instead of in
# SimpleXMLRPCDispatcher. To maintain backwards compatibility,
@@ -481,18 +511,36 @@ class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.send_header("X-exception", str(e))
self.send_header("X-traceback", traceback.format_exc())
+ self.send_header("Content-length", "0")
self.end_headers()
else:
# got a valid XML RPC response
self.send_response(200)
self.send_header("Content-type", "text/xml")
+ if self.encode_threshold is not None:
+ if len(response) > self.encode_threshold:
+ q = self.accept_encodings().get("gzip", 0)
+ if q:
+ response = xmlrpclib.gzip_encode(response)
+ self.send_header("Content-Encoding", "gzip")
self.send_header("Content-length", str(len(response)))
self.end_headers()
self.wfile.write(response)
- # shut down the connection
- self.wfile.flush()
- self.connection.shutdown(1)
+ def decode_request_content(self, data):
+ #support gzip encoding of request
+ encoding = self.headers.get("content-encoding", "identity").lower()
+ if encoding == "identity":
+ return data
+ if encoding == "gzip":
+ try:
+ return xmlrpclib.gzip_decode(data)
+ except ValueError:
+ self.send_response(400, "error decoding gzip content")
+ else:
+ self.send_response(501, "encoding %r not supported" % encoding)
+ self.send_header("Content-length", "0")
+ self.end_headers()
def report_404 (self):
# Report a 404 error
@@ -502,9 +550,6 @@ class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.send_header("Content-length", str(len(response)))
self.end_headers()
self.wfile.write(response)
- # shut down the connection
- self.wfile.flush()
- self.connection.shutdown(1)
def log_request(self, code='-', size='-'):
"""Selectively log an accepted request."""