Changeset 1345
- Timestamp:
- 09/09/06 22:47:10
- Files:
-
- trunk/cherrypy/_cpserver.py (modified) (1 diff)
- trunk/cherrypy/_cpwsgi.py (modified) (1 diff)
- trunk/cherrypy/_cpwsgiserver.py (modified) (7 diffs)
- trunk/cherrypy/test/modpy.py (modified) (1 diff)
- trunk/cherrypy/test/test.pem (added)
- trunk/cherrypy/test/test.py (modified) (11 diffs)
- trunk/cherrypy/test/test_conn.py (modified) (9 diffs)
- trunk/cherrypy/test/test_core.py (modified) (3 diffs)
- trunk/cherrypy/test/test_objectmapping.py (modified) (3 diffs)
- trunk/cherrypy/test/test_proxy.py (modified) (4 diffs)
- trunk/cherrypy/test/test_xmlrpc.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cpserver.py
r1325 r1345 51 51 max_request_body_size = 100 * 1024 * 1024 52 52 instance = None 53 ssl_certificate = None 54 ssl_private_key = None 53 55 54 56 def __init__(self): trunk/cherrypy/_cpwsgi.py
r1310 r1345 138 138 ) 139 139 s.protocol = server.protocol_version 140 s.ssl_certificate = server.ssl_certificate 141 s.ssl_private_key = server.ssl_private_key 140 142 trunk/cherrypy/_cpwsgiserver.py
r1344 r1345 18 18 from urllib import unquote 19 19 from urlparse import urlparse 20 21 try: 22 from OpenSSL import SSL 23 except ImportError: 24 SSL = None 20 25 21 26 import errno … … 342 347 343 348 349 def _ssl_wrap_method(method): 350 def ssl_method_wrapper(self, *args, **kwargs): 351 ## print (id(self), method, args, kwargs) 352 while True: 353 try: 354 return method(self, *args, **kwargs) 355 except (SSL.WantReadError, SSL.WantWriteError): 356 # Sleep and try again 357 time.sleep(self.ssl_retry) 358 except SSL.SysCallError, e: 359 errno = e.args[0] 360 if errno not in socket_errors_to_ignore: 361 raise socket.error(errno) 362 return "" 363 except SSL.Error, e: 364 if e.args == (-1, 'Unexpected EOF'): 365 return "" 366 elif e.args[0][0][2] == 'ssl handshake failure': 367 return "" 368 else: 369 raise 370 ## raise socket.timeout() 371 return ssl_method_wrapper 372 373 class SSL_fileobject(socket._fileobject): 374 """Faux file object attached to a socket object.""" 375 376 ssl_timeout = 3 377 ssl_retry = .01 378 379 close = _ssl_wrap_method(socket._fileobject.close) 380 flush = _ssl_wrap_method(socket._fileobject.flush) 381 write = _ssl_wrap_method(socket._fileobject.write) 382 writelines = _ssl_wrap_method(socket._fileobject.writelines) 383 read = _ssl_wrap_method(socket._fileobject.read) 384 readline = _ssl_wrap_method(socket._fileobject.readline) 385 readlines = _ssl_wrap_method(socket._fileobject.readlines) 386 387 344 388 class HTTPConnection(object): 345 389 346 bufsize = -1 390 rbufsize = -1 391 wbufsize = -1 347 392 RequestHandlerClass = HTTPRequest 348 393 environ = {"wsgi.version": (1, 0), … … 354 399 } 355 400 356 def __init__(self, sock et, addr, server):357 self.socket = sock et401 def __init__(self, sock, addr, server): 402 self.socket = sock 358 403 self.addr = addr 359 404 self.server = server 360 405 361 self.rfile = self.socket.makefile("r", self.bufsize)362 self.wfile = self.socket.makefile("w", self.bufsize)363 364 406 # Copy the class environ into self. 365 407 self.environ = self.environ.copy() 408 409 if type(sock) is socket.socket: 410 self.rfile = self.socket.makefile("r", self.rbufsize) 411 self.wfile = self.socket.makefile("w", self.wbufsize) 412 else: 413 # Assume it's an HTTPS socket wrapper 414 self.environ["wsgi.url_scheme"] = "https" 415 self.rfile = SSL_fileobject(sock, "r", self.rbufsize) 416 self.wfile = SSL_fileobject(sock, "w", self.wbufsize) 417 366 418 self.environ.update({"wsgi.input": self.rfile, 367 419 "SERVER_NAME": self.server.server_name, … … 391 443 req.parse_request() 392 444 if not req.ready: 393 break445 return 394 446 req.respond() 395 447 if req.close_connection: 396 break448 return 397 449 except socket.error, e: 398 450 errno = e.args[0] … … 401 453 req.simple_response("500 Internal Server Error", 402 454 format_exc()) 455 return 403 456 except (KeyboardInterrupt, SystemExit): 404 457 raise … … 469 522 ConnectionClass = HTTPConnection 470 523 524 # Paths to certificate and private key files 525 ssl_certificate = None 526 ssl_private_key = None 527 471 528 def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None, 472 529 max=-1, request_queue_size=5, timeout=10): … … 507 564 self.socket = socket.socket(family, type, proto) 508 565 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 566 if self.ssl_certificate and self.ssl_private_key: 567 # See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473 568 ctx = SSL.Context(SSL.SSLv23_METHOD) 569 ctx.use_privatekey_file(self.ssl_private_key) 570 ctx.use_certificate_file(self.ssl_certificate) 571 self.socket = SSL.Connection(ctx, self.socket) 509 572 self.socket.bind(self.bind_addr) 510 573 trunk/cherrypy/test/modpy.py
r1326 r1345 133 133 webtest.WebCase.PORT = self.port 134 134 webtest.WebCase.harness = self 135 webtest.WebCase.scheme = "http" 135 136 print 136 137 print "Running tests:", self.server trunk/cherrypy/test/test.py
r1343 r1345 11 11 12 12 13 import getopt 14 import httplib 15 import os, os.path 16 localDir = os.path.dirname(__file__) 17 serverpem = os.path.join(os.getcwd(), localDir, 'test.pem') 13 18 import sys 14 import os, os.path15 import getopt16 19 17 20 … … 19 22 """A test harness for the CherryPy framework and CherryPy applications.""" 20 23 21 def __init__(self, tests=None, server=None, protocol="HTTP/1.1", port=8000): 24 def __init__(self, tests=None, server=None, protocol="HTTP/1.1", 25 port=8000, scheme="http"): 22 26 """Constructor to populate the TestHarness instance. 23 27 24 28 tests should be a list of module names (strings). 25 29 """ 30 self.tests = tests or [] 31 self.server = server 26 32 self.protocol = protocol 27 33 self.port = port 28 self.server = server 29 self.tests = tests or [] 34 self.scheme = scheme 30 35 31 36 def run(self, conf=None): … … 35 40 print "Python version used to run this test script:", v 36 41 print "CherryPy version", cherrypy.__version__ 37 print "HTTP server version", self.protocol 42 if self.scheme == "https": 43 ssl = "(ssl)" 44 else: 45 ssl = "" 46 print "HTTP server version", self.protocol, ssl 38 47 print 39 48 … … 48 57 49 58 baseconf['server.protocol_version'] = self.protocol 59 if self.scheme == "https": 60 baseconf['server.ssl_certificate'] = serverpem 61 baseconf['server.ssl_private_key'] = serverpem 50 62 self._run(baseconf) 51 63 … … 60 72 webtest.WebCase.PORT = self.port 61 73 webtest.WebCase.harness = self 74 webtest.WebCase.scheme = self.scheme 75 if self.scheme == "https": 76 webtest.WebCase.HTTP_CONN = httplib.HTTPSConnection 62 77 print 63 78 print "Running tests:", self.server … … 71 86 } 72 87 default_server = "wsgi" 88 scheme = "http" 89 protocol = "HTTP/1.1" 73 90 port = 8080 91 cover = False 92 profile = False 93 validate = False 94 server = None 74 95 basedir = None 75 96 … … 83 104 """ 84 105 self.available_tests = available_tests 85 self.cover = False 86 self.profile = False 87 self.validate = False 88 self.server = None 89 self.protocol = "HTTP/1.1" 90 91 longopts = ['cover', 'profile', 'validate', '1.0', 'help', 'basedir=', 'port=', 92 'server='] 106 107 longopts = ['cover', 'profile', 'validate', '1.0', 'ssl', 'help', 108 'basedir=', 'port=', 'server='] 93 109 longopts.extend(self.available_tests) 94 110 try: … … 113 129 elif o == "--1.0": 114 130 self.protocol = "HTTP/1.0" 131 elif o == "--ssl": 132 self.scheme = "https" 115 133 elif o == "--basedir": 116 134 self.basedir = a … … 217 235 if basedir is None: 218 236 # Assume we want to cover everything in "../../cherrypy/" 219 localDir = os.path.dirname(__file__)220 237 basedir = os.path.normpath(os.path.join(os.getcwd(), localDir, '../')) 221 238 else: … … 284 301 h.use_wsgi = True 285 302 else: 286 h = TestHarness(self.tests, self.server, self.protocol, self.port) 303 h = TestHarness(self.tests, self.server, self.protocol, 304 self.port, self.scheme) 287 305 288 306 h.run(conf) … … 300 318 # Place this __file__'s grandparent (../../) at the start of sys.path, 301 319 # so that all cherrypy/* imports are from this __file__'s package. 302 localDir = os.path.dirname(__file__)303 320 curpath = os.path.normpath(os.path.join(os.getcwd(), localDir)) 304 321 grandparent = os.path.normpath(os.path.join(curpath, '../../')) trunk/cherrypy/test/test_conn.py
r1326 r1345 58 58 59 59 # Set our HTTP_CONN to an instance so it persists between requests. 60 self.HTTP_CONN = httplib.HTTPConnection(self.HOST, self.PORT) 60 if self.scheme == "https": 61 self.HTTP_CONN = httplib.HTTPSConnection(self.HOST, self.PORT) 62 else: 63 self.HTTP_CONN = httplib.HTTPConnection(self.HOST, self.PORT) 61 64 # Don't automatically re-connect 62 65 self.HTTP_CONN.auto_open = False … … 94 97 95 98 # Test client-side close. 96 self.HTTP_CONN = httplib.HTTPConnection(self.HOST, self.PORT) 99 if self.scheme == "https": 100 self.HTTP_CONN = httplib.HTTPSConnection(self.HOST, self.PORT) 101 else: 102 self.HTTP_CONN = httplib.HTTPConnection(self.HOST, self.PORT) 97 103 self.HTTP_CONN.auto_open = False 98 104 self.HTTP_CONN.connect() … … 123 129 124 130 # Make an initial request 125 conn = httplib.HTTPConnection(self.HOST, self.PORT) 131 if self.scheme == "https": 132 conn = httplib.HTTPSConnection(self.HOST, self.PORT) 133 else: 134 conn = httplib.HTTPConnection(self.HOST, self.PORT) 126 135 conn.auto_open = False 127 136 conn.connect() … … 162 171 else: 163 172 self.fail("Writing to timed out socket didn't fail" 164 " as it should have.") 173 " as it should have: %s" % 174 response.read()) 165 175 166 176 conn.close() 167 177 168 178 # Make another request on a new socket, which should work 169 conn = httplib.HTTPConnection(self.HOST, self.PORT) 179 if self.scheme == "https": 180 conn = httplib.HTTPSConnection(self.HOST, self.PORT) 181 else: 182 conn = httplib.HTTPConnection(self.HOST, self.PORT) 170 183 conn.auto_open = False 171 184 conn.connect() … … 190 203 191 204 # Test pipelining. httplib doesn't support this directly. 192 conn = httplib.HTTPConnection(self.HOST, self.PORT) 205 if self.scheme == "https": 206 conn = httplib.HTTPSConnection(self.HOST, self.PORT) 207 else: 208 conn = httplib.HTTPConnection(self.HOST, self.PORT) 193 209 conn.auto_open = False 194 210 conn.connect() … … 227 243 self.PROTOCOL = "HTTP/1.1" 228 244 229 conn = httplib.HTTPConnection(self.HOST, self.PORT) 245 if self.scheme == "https": 246 conn = httplib.HTTPSConnection(self.HOST, self.PORT) 247 else: 248 conn = httplib.HTTPConnection(self.HOST, self.PORT) 230 249 conn.auto_open = False 231 250 conn.connect() … … 286 305 287 306 # Set our HTTP_CONN to an instance so it persists between requests. 288 conn = httplib.HTTPConnection(self.HOST, self.PORT) 307 if self.scheme == "https": 308 conn = httplib.HTTPSConnection(self.HOST, self.PORT) 309 else: 310 conn = httplib.HTTPConnection(self.HOST, self.PORT) 289 311 290 312 # Try a normal chunked request … … 323 345 def test_HTTP10(self): 324 346 self.PROTOCOL = "HTTP/1.0" 325 self.HTTP_CONN = httplib.HTTPConnection 347 if self.scheme == "https": 348 self.HTTP_CONN = httplib.HTTPSConnection 349 else: 350 self.HTTP_CONN = httplib.HTTPConnection 326 351 327 352 # Test a normal HTTP/1.0 request. … … 333 358 334 359 # Test a keep-alive HTTP/1.0 request. 335 self.HTTP_CONN = httplib.HTTPConnection(self.HOST, self.PORT) 360 if self.scheme == "https": 361 self.HTTP_CONN = httplib.HTTPSConnection(self.HOST, self.PORT) 362 else: 363 self.HTTP_CONN = httplib.HTTPConnection(self.HOST, self.PORT) 336 364 self.HTTP_CONN.auto_open = False 337 365 self.HTTP_CONN.connect() trunk/cherrypy/test/test_core.py
r1329 r1345 513 513 self.getPage("/redirect?id=3") 514 514 self.assertStatus(('302 Found', '303 See Other')) 515 self.assertInBody("<a href='http://127.0.0.1:%s%s/redirect/?id=3'>" 516 "http://127.0.0.1:%s%s/redirect/?id=3</a>" % 517 (self.PORT, self.prefix(), self.PORT, self.prefix())) 515 self.assertInBody("<a href='%s://127.0.0.1:%s%s/redirect/?id=3'>" 516 "%s://127.0.0.1:%s%s/redirect/?id=3</a>" % 517 (self.scheme, self.PORT, self.prefix(), 518 self.scheme, self.PORT, self.prefix())) 518 519 519 520 if self.prefix(): … … 522 523 self.getPage("") 523 524 self.assertStatus(('302 Found', '303 See Other')) 524 self.assertInBody("<a href='http://127.0.0.1:%s%s/'>" 525 "http://127.0.0.1:%s%s/</a>" % 526 (self.PORT, self.prefix(), self.PORT, self.prefix())) 525 self.assertInBody("<a href='%s://127.0.0.1:%s%s/'>" 526 "%s://127.0.0.1:%s%s/</a>" % 527 (self.scheme, self.PORT, self.prefix(), 528 self.scheme, self.PORT, self.prefix())) 527 529 528 530 self.getPage("/redirect/by_code?code=300") … … 593 595 self.getPage("/redirect/stringify", protocol="HTTP/1.0") 594 596 self.assertStatus(200) 595 self.assertBody("([' http://127.0.0.1:%s/'], 302)" % self.PORT)597 self.assertBody("(['%s://127.0.0.1:%s/'], 302)" % (self.scheme, self.PORT)) 596 598 if cherrypy.server.protocol_version == "HTTP/1.1": 597 599 self.getPage("/redirect/stringify", protocol="HTTP/1.1") 598 600 self.assertStatus(200) 599 self.assertBody("([' http://127.0.0.1:%s/'], 303)" % self.PORT)601 self.assertBody("(['%s://127.0.0.1:%s/'], 303)" % (self.scheme, self.PORT)) 600 602 601 603 def testFlatten(self): trunk/cherrypy/test/test_objectmapping.py
r1342 r1345 182 182 self.getPage("/dir1/dir2") 183 183 self.assertStatus((302, 303)) 184 self.assertHeader('Location', ' http://%s:%s%s/dir1/dir2/'185 % (self. HOST, self.PORT, prefix))184 self.assertHeader('Location', '%s://%s:%s%s/dir1/dir2/' 185 % (self.scheme, self.HOST, self.PORT, prefix)) 186 186 187 187 # Test extra trailing slash (should be redirected if configured). 188 188 self.getPage("/dir1/myMethod/") 189 189 self.assertStatus((302, 303)) 190 self.assertHeader('Location', ' http://%s:%s%s/dir1/myMethod'191 % (self. HOST, self.PORT, prefix))190 self.assertHeader('Location', '%s://%s:%s%s/dir1/myMethod' 191 % (self.scheme, self.HOST, self.PORT, prefix)) 192 192 193 193 # Test that default method must be exposed in order to match. … … 203 203 self.getPage("/redirect") 204 204 self.assertStatus('302 Found') 205 self.assertHeader('Location', ' http://%s:%s%s/dir1/'206 % (self. HOST, self.PORT, prefix))205 self.assertHeader('Location', '%s://%s:%s%s/dir1/' 206 % (self.scheme, self.HOST, self.PORT, prefix)) 207 207 208 208 # Test that we can use URL's which aren't all valid Python identifiers … … 220 220 self.assertBody(url) 221 221 self.getPage("/dir1/dir2/tree_url") 222 self.assertBody(" http://%s:%s%s/extra" %223 (self. HOST, self.PORT, prefix))222 self.assertBody("%s://%s:%s%s/extra" % 223 (self.scheme, self.HOST, self.PORT, prefix)) 224 224 225 225 # Test that configs don't overwrite each other from diferent apps trunk/cherrypy/test/test_proxy.py
r1339 r1345 47 47 self.getPage("/") 48 48 self.assertHeader('Location', 49 " http://www.mydomain.com%s/dummy" % self.prefix())49 "%s://www.mydomain.com%s/dummy" % (self.scheme, self.prefix())) 50 50 51 51 # Test X-Forwarded-Host (Apache 1.3.33+ and Apache 2) … … 53 53 self.assertHeader('Location', "http://www.yetanother.com/dummy") 54 54 self.getPage("/", headers=[('X-Forwarded-Host', 'www.yetanother.com')]) 55 self.assertHeader('Location', " http://www.yetanother.com/dummy")55 self.assertHeader('Location', "%s://www.yetanother.com/dummy" % self.scheme) 56 56 57 57 # Test X-Forwarded-For (Apache2) … … 65 65 # Test X-Host (lighttpd; see https://trac.lighttpd.net/trac/ticket/418) 66 66 self.getPage("/xhost", headers=[('X-Host', 'www.yetanother.com')]) 67 self.assertHeader('Location', " http://www.yetanother.com/blah")67 self.assertHeader('Location', "%s://www.yetanother.com/blah" % self.scheme) 68 68 69 69 # Test X-Forwarded-Proto (lighttpd) … … 74 74 for sn in script_names: 75 75 self.getPage(sn + "/newurl") 76 self.assertBody("Browse to <a href=' http://www.mydomain.com"76 self.assertBody("Browse to <a href='%s://www.mydomain.com" % self.scheme 77 77 + sn + "/this/new/page'>this page</a>.") 78 78 self.getPage(sn + "/newurl", headers=[('X-Forwarded-Host', trunk/cherrypy/test/test_xmlrpc.py
r1275 r1345 62 62 63 63 64 class HTTPSTransport(xmlrpclib.SafeTransport): 65 """Subclass of SafeTransport to fix sock.recv errors (by using file).""" 66 67 def request(self, host, handler, request_body, verbose=0): 68 # issue XML-RPC request 69 h = self.make_connection(host) 70 if verbose: 71 h.set_debuglevel(1) 72 73 self.send_request(h, handler, request_body) 74 self.send_host(h, host) 75 self.send_user_agent(h) 76 self.send_content(h, request_body) 77 78 errcode, errmsg, headers = h.getreply() 79 if errcode != 200: 80 raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, 81 headers) 82 83 self.verbose = verbose 84 return self.parse_response(h.getfile()) 85 86 64 87 from cherrypy.test import helper 65 88 … … 68 91 69 92 # load the appropriate xmlrpc proxy 70 url = 'http://localhost:%s/xmlrpc/' % (self.PORT) 71 proxy = xmlrpclib.ServerProxy(url) 93 if getattr(self.harness, "scheme", "http") == "https": 94 url = 'https://localhost:%s/xmlrpc/' % self.PORT 95 proxy = xmlrpclib.ServerProxy(url, transport=HTTPSTransport()) 96 else: 97 url = 'http://localhost:%s/xmlrpc/' % self.PORT 98 proxy = xmlrpclib.ServerProxy(url) 72 99 73 100 # begin the tests ...

