Changeset 388 for python/vendor/current/Lib/SimpleXMLRPCServer.py
- Timestamp:
- Mar 19, 2014, 11:11:30 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
python/vendor/current/Lib/SimpleXMLRPCServer.py
r2 r388 1 """Simple XML-RPC Server.1 r"""Simple XML-RPC Server. 2 2 3 3 This module can be used to create simple XML-RPC servers … … 107 107 import os 108 108 import traceback 109 import re 109 110 try: 110 111 import fcntl … … 161 162 162 163 This class is used to register XML-RPC method handlers 163 and then to dispatch them. There should never be any 164 reason to instantiate this class directly. 164 and then to dispatch them. This class doesn't need to be 165 instanced directly when used by SimpleXMLRPCServer but it 166 can be instanced when used by the MultiPathXMLRPCServer. 165 167 """ 166 168 … … 237 239 self.funcs.update({'system.multicall' : self.system_multicall}) 238 240 239 def _marshaled_dispatch(self, data, dispatch_method = None ):241 def _marshaled_dispatch(self, data, dispatch_method = None, path = None): 240 242 """Dispatches an XML-RPC method from marshalled (XML) data. 241 243 … … 245 247 function can be provided as an argument (see comment in 246 248 SimpleXMLRPCRequestHandler.do_POST) but overriding the 247 existing method through subclassing is the prefer ed means249 existing method through subclassing is the preferred means 248 250 of changing method dispatch behavior. 249 251 """ … … 431 433 rpc_paths = ('/', '/RPC2') 432 434 435 #if not None, encode responses larger than this, if possible 436 encode_threshold = 1400 #a common MTU 437 438 #Override form StreamRequestHandler: full buffering of output 439 #and no Nagle. 440 wbufsize = -1 441 disable_nagle_algorithm = True 442 443 # a re to match a gzip Accept-Encoding 444 aepattern = re.compile(r""" 445 \s* ([^\s;]+) \s* #content-coding 446 (;\s* q \s*=\s* ([0-9\.]+))? #q 447 """, re.VERBOSE | re.IGNORECASE) 448 449 def accept_encodings(self): 450 r = {} 451 ae = self.headers.get("Accept-Encoding", "") 452 for e in ae.split(","): 453 match = self.aepattern.match(e) 454 if match: 455 v = match.group(3) 456 v = float(v) if v else 1.0 457 r[match.group(1)] = v 458 return r 459 433 460 def is_rpc_path_valid(self): 434 461 if self.rpc_paths: … … 460 487 while size_remaining: 461 488 chunk_size = min(size_remaining, max_chunk_size) 462 L.append(self.rfile.read(chunk_size)) 489 chunk = self.rfile.read(chunk_size) 490 if not chunk: 491 break 492 L.append(chunk) 463 493 size_remaining -= len(L[-1]) 464 494 data = ''.join(L) 495 496 data = self.decode_request_content(data) 497 if data is None: 498 return #response has been sent 465 499 466 500 # In previous versions of SimpleXMLRPCServer, _dispatch … … 470 504 # using that method if present. 471 505 response = self.server._marshaled_dispatch( 472 data, getattr(self, '_dispatch', None) 506 data, getattr(self, '_dispatch', None), self.path 473 507 ) 474 508 except Exception, e: # This should only happen if the module is buggy … … 482 516 self.send_header("X-traceback", traceback.format_exc()) 483 517 518 self.send_header("Content-length", "0") 484 519 self.end_headers() 485 520 else: … … 487 522 self.send_response(200) 488 523 self.send_header("Content-type", "text/xml") 524 if self.encode_threshold is not None: 525 if len(response) > self.encode_threshold: 526 q = self.accept_encodings().get("gzip", 0) 527 if q: 528 try: 529 response = xmlrpclib.gzip_encode(response) 530 self.send_header("Content-Encoding", "gzip") 531 except NotImplementedError: 532 pass 489 533 self.send_header("Content-length", str(len(response))) 490 534 self.end_headers() 491 535 self.wfile.write(response) 492 536 493 # shut down the connection 494 self.wfile.flush() 495 self.connection.shutdown(1) 537 def decode_request_content(self, data): 538 #support gzip encoding of request 539 encoding = self.headers.get("content-encoding", "identity").lower() 540 if encoding == "identity": 541 return data 542 if encoding == "gzip": 543 try: 544 return xmlrpclib.gzip_decode(data) 545 except NotImplementedError: 546 self.send_response(501, "encoding %r not supported" % encoding) 547 except ValueError: 548 self.send_response(400, "error decoding gzip content") 549 else: 550 self.send_response(501, "encoding %r not supported" % encoding) 551 self.send_header("Content-length", "0") 552 self.end_headers() 496 553 497 554 def report_404 (self): … … 503 560 self.end_headers() 504 561 self.wfile.write(response) 505 # shut down the connection506 self.wfile.flush()507 self.connection.shutdown(1)508 562 509 563 def log_request(self, code='-', size='-'): … … 547 601 fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags) 548 602 603 class MultiPathXMLRPCServer(SimpleXMLRPCServer): 604 """Multipath XML-RPC Server 605 This specialization of SimpleXMLRPCServer allows the user to create 606 multiple Dispatcher instances and assign them to different 607 HTTP request paths. This makes it possible to run two or more 608 'virtual XML-RPC servers' at the same port. 609 Make sure that the requestHandler accepts the paths in question. 610 """ 611 def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, 612 logRequests=True, allow_none=False, encoding=None, bind_and_activate=True): 613 614 SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests, allow_none, 615 encoding, bind_and_activate) 616 self.dispatchers = {} 617 self.allow_none = allow_none 618 self.encoding = encoding 619 620 def add_dispatcher(self, path, dispatcher): 621 self.dispatchers[path] = dispatcher 622 return dispatcher 623 624 def get_dispatcher(self, path): 625 return self.dispatchers[path] 626 627 def _marshaled_dispatch(self, data, dispatch_method = None, path = None): 628 try: 629 response = self.dispatchers[path]._marshaled_dispatch( 630 data, dispatch_method, path) 631 except: 632 # report low level exception back to server 633 # (each dispatcher should have handled their own 634 # exceptions) 635 exc_type, exc_value = sys.exc_info()[:2] 636 response = xmlrpclib.dumps( 637 xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)), 638 encoding=self.encoding, allow_none=self.allow_none) 639 return response 640 549 641 class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): 550 642 """Simple handler for XML-RPC data passed through CGI.""" … … 581 673 } 582 674 print 'Status: %d %s' % (code, message) 583 print 'Content-Type: text/html'675 print 'Content-Type: %s' % BaseHTTPServer.DEFAULT_ERROR_CONTENT_TYPE 584 676 print 'Content-Length: %d' % len(response) 585 677 print
Note:
See TracChangeset
for help on using the changeset viewer.