Changeset 480
- Timestamp:
- 07/18/05 12:38:27
- Files:
-
- trunk/cherrypy/_cperror.py (modified) (1 diff)
- trunk/cherrypy/_cphttptools.py (modified) (11 diffs)
- trunk/cherrypy/lib/autoreload.py (modified) (3 diffs)
- trunk/cherrypy/test/helper.py (modified) (2 diffs)
- trunk/cherrypy/test/test.py (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cperror.py
r405 r480 117 117 # http://ppewww.ph.gla.ac.uk/~flavell/www/post-redirect.html 118 118 if status is None: 119 if cherrypy.request. protocol == "HTTP/1.1":119 if cherrypy.request.version >= "1.1": 120 120 status = 303 121 121 else: trunk/cherrypy/_cphttptools.py
r475 r480 31 31 """ 32 32 33 import urllib, os, sys, time, types, cgi 33 import urllib, os, sys, time, types, cgi, re 34 34 import mimetypes, Cookie 35 35 … … 67 67 return ("%s, %02d %3s %4d %02d:%02d:%02d GMT" % 68 68 (weekdayname[wd], day, monthname[month], year, hh, mm, ss)) 69 70 71 class Version(object): 72 73 def __init__(self, atoms): 74 if isinstance(atoms, basestring): 75 self.atoms = re.split(r'\W', atoms) 76 else: 77 self.atoms = [str(x) for x in atoms] 78 79 def from_http(cls, version_str): 80 return cls(version_str[5:]) 81 from_http = classmethod(from_http) 82 83 def to_http(self): 84 return "HTTP/%s.%s" % tuple(self.atoms[:2]) 85 86 def __str__(self): 87 return ".".join([str(x) for x in self.atoms]) 88 89 def __cmp__(self, other): 90 cls = self.__class__ 91 if not isinstance(other, cls): 92 # Try to coerce other to a Version instance. 93 other = cls(other) 94 95 index = 0 96 while index < len(self.atoms) and index < len(other.atoms): 97 mine, theirs = self.atoms[index], other.atoms[index] 98 if mine.isdigit() and theirs.isdigit(): 99 mine, theirs = int(mine), int(theirs) 100 if mine < theirs: 101 return -1 102 if mine > theirs: 103 return 1 104 index += 1 105 if index < len(other.atoms): 106 return -1 107 if index < len(self.atoms): 108 return 1 109 return 0 69 110 70 111 … … 125 166 def __init__(self, clientAddress, remoteHost, requestLine, headers, 126 167 rfile, scheme="http"): 127 # When __init__ is finished, cherrypy.response should have threeattributes:168 # When __init__ is done, cherrypy.response should have 3 attributes: 128 169 # status, e.g. "200 OK" 129 170 # headers, a list of (name, value) tuples … … 157 198 "Date": httpdate(), 158 199 "Set-Cookie": [], 159 "Content-Length": 0200 "Content-Length": None 160 201 }) 161 202 cherrypy.response.simpleCookie = Cookie.SimpleCookie() … … 204 245 req.processRequestBody = req.method in ("POST", "PUT") 205 246 247 # Compare request and server HTTP versions, in case our server does 248 # not support the requested version. We can't tell the server what 249 # version number to write in the response, so we limit our output 250 # to min(req, server). We want the following output: 251 # request version server version response version features 252 # a 1.0 1.0 1.0 1.0 253 # b 1.0 1.1 1.1 1.0 254 # c 1.1 1.0 1.0 1.0 255 # d 1.1 1.1 1.1 1.1 256 # Notice that, in (b), the response will be "HTTP/1.1" even though 257 # the client only understands 1.0. RFC 2616 10.5.6 says we should 258 # only return 505 if the _major_ version is different. 259 request_v = Version.from_http(req.protocol) 260 server_v = cherrypy.config.get("server.protocolVersion", "HTTP/1.0") 261 server_v = Version.from_http(server_v) 262 cherrypy.request.version = min(request_v, server_v) 263 206 264 # find the queryString, or set it to "" if not found 207 265 if "?" in path: … … 234 292 cherrypy.log(msg, "HTTP") 235 293 236 req.base = "%s://%s" % (req.scheme, req.headerMap.get('Host', ''))237 req.browserUrl = req.base + path238 239 294 # Change objectPath in filters to change 240 295 # the object that will get rendered … … 245 300 req.originalParamMap = req.paramMap 246 301 req.originalParamList = req.paramList 302 303 if cherrypy.request.version >= "1.1": 304 # All Internet-based HTTP/1.1 servers MUST respond with a 400 305 # (Bad Request) status code to any HTTP/1.1 request message 306 # which lacks a Host header field. 307 if not req.headerMap.has_key("Host"): 308 cherrypy.response.status = 400 309 cherrypy.response.body = ["HTTP/1.1 requires a 'Host' request header."] 310 finalize() 311 raise cherrypy.RequestHandled 312 req.base = "%s://%s" % (req.scheme, req.headerMap.get('Host', '')) 313 req.browserUrl = req.base + path 247 314 248 315 def processRequestBody(self): … … 431 498 cherrypy.response.body = [] 432 499 433 if (cherrypy.config.get("server.protocolVersion") != "HTTP/1.1"434 and cherrypy.response.headerMap.get('Content-Length') == 0):435 content = ''.join([chunk for chunk in cherrypy.response.body])436 cherrypy.response.body = [content]437 cherrypy.response.headerMap['Content-Length'] = len(content)500 if cherrypy.response.headerMap.get('Content-Length') is None: 501 if cherrypy.request.version < "1.1": 502 content = ''.join([chunk for chunk in cherrypy.response.body]) 503 cherrypy.response.body = [content] 504 cherrypy.response.headerMap['Content-Length'] = len(content) 438 505 439 506 # Headers … … 506 573 except OSError: 507 574 raise cherrypy.NotFound(cherrypy.request.path) 508 575 509 576 # Set content-type based on filename extension 510 577 i = filename.rfind('.') … … 513 580 else: 514 581 ext = "" 515 582 516 583 contentType = mimetypes.types_map.get(ext, "text/plain") 517 584 cherrypy.response.headerMap['Content-Type'] = contentType … … 531 598 bodyfile = open(filename, 'rb') 532 599 cherrypy.response.body = fileGenerator(bodyfile) 533 534 535 600 536 601 trunk/cherrypy/lib/autoreload.py
r277 r480 6 6 import time 7 7 import thread 8 from cherrypy import _cputil 8 import cherrypy 9 9 10 10 RUN_RELOADER = True … … 28 28 while True: 29 29 args = [sys.executable] + sys.argv 30 if sys.platform == "win32": args = ['"%s"' % arg for arg in args] 30 if sys.platform == "win32": 31 args = ['"%s"' % arg for arg in args] 31 32 new_environ = os.environ.copy() 32 33 new_environ["RUN_MAIN"] = 'true' … … 53 54 sys.exit(restart_with_reloader()) 54 55 except KeyboardInterrupt: 55 _cputil.getSpecialAttribute('_cpLogMessage')("<Ctrl-C> hit: shutting down autoreloader", "HTTP")56 cherrypy.log("<Ctrl-C> hit: shutting down autoreloader", "HTTP") trunk/cherrypy/test/helper.py
r477 r480 88 88 self.url = url 89 89 90 requestLine = "%s %s HTTP/1. 0" % (method.upper(), url)90 requestLine = "%s %s HTTP/1.1" % (method.upper(), url) 91 91 headers = webtest.cleanHeaders(headers, method, body, HOST, PORT) 92 92 if body is not None: … … 175 175 176 176 177 def testmain(server=None, conf={}): 177 def testmain(server=None, conf=None): 178 if conf is None: 179 conf = {} 180 ## conf = {'global': {'server.socketHost': HOST, 181 ## 'server.socketPort': PORT, 182 ## 'server.protocolVersion': "HTTP/1.1", 183 ## 'server.threadPool': 10, 184 ## 'server.logToScreen': False, 185 ## 'server.environment': "production", 186 ## } 187 ## } 188 ## if server is None: 189 ## server = "cherrypy._cphttpserver.embedded_server" 178 190 if isinstance(conf, basestring): 179 191 # assume it's a filename trunk/cherrypy/test/test.py
r474 r480 74 74 75 75 76 def getOptions(args): 77 78 argSet = set([arg.lower() for arg in args]) 79 80 if '-help' in args: 81 raise DisplayHelp 82 83 servers = set() 84 if '-all' in argSet: 85 servers.update(['wsgi', 'native', 'serverless']) 86 else: 87 if '-native' in argSet: 88 servers.add('native') 89 if '-serverless' in argSet: 90 servers.add('serverless') 91 if '-wsgi' in argSet or not servers: 92 servers.add('wsgi') 93 argSet.difference_update(['-wsgi', '-native', '-serverless', '-all']) 94 95 cover = ("-cover" in argSet) 96 profile = ("-profile" in argSet) 97 if cover and profile: 98 raise BadArgument('Bad Arguments: you cannot run the profiler and the coverage tool at the same time.') 99 argSet.difference_update(['-cover', '-profile']) 100 101 tests = [] 102 for testString, test in testDict.iteritems(): 103 if testString.lower() in argSet: 104 tests.append(testDict[testString]) 105 argSet.discard(testString.lower()) 106 if not tests: 107 tests = testDict.values() 108 109 if len(argSet): 110 for arg in args: 111 if arg.lower() in argSet: 112 raise BadArgument('Bad Argument: %s is not a valid option.' % arg) 113 return (servers, tests, cover, profile) 114 115 116 def main(servers, testList, cover=False, profile=False): 76 class Options: 77 78 def __init__(self, args): 79 argSet = set([arg.lower() for arg in args]) 80 81 if '-help' in args: 82 raise DisplayHelp 83 84 servers = set() 85 if '-all' in argSet: 86 servers.update(['wsgi', 'native', 'serverless']) 87 else: 88 if '-native' in argSet: 89 servers.add('native') 90 if '-serverless' in argSet: 91 servers.add('serverless') 92 if '-wsgi' in argSet or not servers: 93 servers.add('wsgi') 94 self.servers = servers 95 argSet.difference_update(['-wsgi', '-native', '-serverless', '-all']) 96 97 self.cover = ("-cover" in argSet) 98 self.profile = ("-profile" in argSet) 99 if self.cover and self.profile: 100 raise BadArgument('Bad Arguments: you cannot run the profiler and the coverage tool at the same time.') 101 argSet.difference_update(['-cover', '-profile']) 102 103 if "-1.1" in argSet: 104 self.protocol = "HTTP/1.1" 105 argSet.difference_update(['-1.1']) 106 else: 107 self.protocol = "HTTP/1.0" 108 109 # All remaining args should be test names. 110 tests = [] 111 for testString, test in testDict.iteritems(): 112 if testString.lower() in argSet: 113 tests.append(testDict[testString]) 114 argSet.discard(testString.lower()) 115 if not tests: 116 tests = testDict.values() 117 self.tests = tests 118 119 if len(argSet): 120 for arg in args: 121 if arg.lower() in argSet: 122 raise BadArgument('Bad Argument: %s is not a valid option.' % arg) 123 124 125 def main(opts): 117 126 # Place our current directory's parent (cherrypy/) at the beginning 118 127 # of sys.path, so that all imports are from our current directory. … … 121 130 sys.path.insert(0, os.path.normpath(os.path.join(curpath, '../../'))) 122 131 123 if cover:132 if opts.cover: 124 133 # Start the coverage tool before importing cherrypy, 125 134 # so module-level global statements are covered. … … 152 161 server_conf = {'global': {'server.socketHost': helper.HOST, 153 162 'server.socketPort': helper.PORT, 163 'server.protocolVersion': opts.protocol, 154 164 'server.threadPool': 10, 155 165 'server.logToScreen': False, … … 158 168 } 159 169 160 if cover:170 if opts.cover: 161 171 cherrypy.codecoverage = True 162 172 163 if profile:173 if opts.profile: 164 174 server_conf['profiling.on'] = True 165 175 166 if 'serverless' in servers: 167 print 168 print "Running testList: Serverless" 169 helper.run_test_suite(testList, None, server_conf) 170 171 if 'native' in servers: 172 print 173 print "Running testList: Native HTTP Server" 174 helper.run_test_suite(testList, "cherrypy._cphttpserver.embedded_server", server_conf) 175 176 if 'wsgi' in servers: 177 print 178 print "Running testList: Native WSGI Server" 179 helper.run_test_suite(testList, "cherrypy._cpwsgi.WSGIServer", server_conf) 180 181 if profile or cover: 182 print 183 184 if profile: 176 if 'serverless' in opts.servers: 177 print 178 print "Running tests: Serverless" 179 helper.run_test_suite(opts.tests, None, server_conf) 180 181 if 'native' in opts.servers: 182 print 183 print "Running tests: Native HTTP Server" 184 helper.run_test_suite(opts.tests, 185 "cherrypy._cphttpserver.embedded_server", 186 server_conf) 187 188 if 'wsgi' in opts.servers: 189 print 190 print "Running tests: Native WSGI Server" 191 helper.run_test_suite(opts.tests, 192 "cherrypy._cpwsgi.WSGIServer", 193 server_conf) 194 195 if opts.profile or opts.cover: 196 print 197 198 if opts.profile: 185 199 del server_conf['profiling.on'] 186 200 print "run /cherrypy/lib/profiler.py as a script to serve profiling results on port 8080" 187 201 188 if cover:202 if opts.cover: 189 203 cherrypy.codecoverage = False 190 204 if coverage: … … 199 213 if __name__ == '__main__': 200 214 try: 201 servers, testList, cover, profile = getOptions(sys.argv[1:])215 opts = Options(sys.argv[1:]) 202 216 except DisplayHelp: 203 217 help() … … 205 219 print argError 206 220 else: 207 main( servers, testList, cover, profile)221 main(opts)

