Changeset 339
- Timestamp:
- 06/17/05 14:48:32
- Files:
-
- trunk/cherrypy/_cphttpserver.py (modified) (2 diffs)
- trunk/cherrypy/_cphttptools.py (modified) (4 diffs)
- trunk/cherrypy/_cpwsgi.py (modified) (2 diffs)
- trunk/cherrypy/test/test_core.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cphttpserver.py
r277 r339 70 70 return list 71 71 72 def doMethod(self): 72 def handle_one_request(self): 73 """Handle a single HTTP request.""" 74 75 self.raw_requestline = self.rfile.readline() 76 if not self.raw_requestline: 77 self.close_connection = 1 78 return 79 if not self.parse_request(): # An error code has been sent, just exit 80 return 81 73 82 cpg.request.multithread = cpg.config.get("server.threadPool") > 1 74 83 cpg.request.multiprocess = False … … 92 101 for chunk in b: 93 102 wfile.write(chunk) 94 95 do_GET = doMethod 96 do_HEAD = doMethod 97 98 def do_POST(self): 99 """Serve a POST request.""" 100 self.doMethod() 101 # What does this line do? 102 self.connection = self.request 103 104 if self.command == "POST": 105 self.connection = self.request 103 106 104 107 def log_message(self, format, *args): trunk/cherrypy/_cphttptools.py
r338 r339 114 114 self.requestLine = requestLine 115 115 self.requestHeaders = headers 116 self.rfile = rfile117 116 118 117 # Prepare cpg.request variables … … 123 122 cpg.request.requestLine = requestLine 124 123 cpg.request.simpleCookie = Cookie.SimpleCookie() 125 cpg.request.rfile = self.rfile124 cpg.request.rfile = rfile 126 125 127 126 # Prepare cpg.response variables … … 144 143 145 144 self.run() 145 146 if cpg.request.method == "HEAD": 147 # HEAD requests MUST NOT return a message-body in the response. 148 cpg.response.body = [] 146 149 147 150 def run(self): … … 223 226 for key, value in cpg.request.headerMap.items(): 224 227 lowerHeaderMap[key.lower()] = value 225 forms = _cpcgifs.FieldStorage(fp = self.rfile, headers =lowerHeaderMap,228 forms = _cpcgifs.FieldStorage(fp=cpg.request.rfile, headers=lowerHeaderMap, 226 229 environ = {'REQUEST_METHOD': 'POST'}, 227 230 keep_blank_values = 1) trunk/cherrypy/_cpwsgi.py
r277 r339 100 100 # not take any time at all if chunk is already of type "str". 101 101 # If it's unicode, it could be a big performance hit (x ~500). 102 yield str(chunk) 102 chunk = str(chunk) 103 yield chunk 103 104 except: 104 105 tb = _cphttptools.formatExc() … … 116 117 # Server components 117 118 118 class WSGIRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):119 120 server_version = "CherryPyWSGI/2.1"121 os_environ = dict(os.environ.items())122 123 def handle_one_request(self):124 """Handle a single HTTP request. Overridden to handle all verbs."""125 response = None126 self.headers_sent = False127 self.responseHeaders = []128 try:129 try:130 self.raw_requestline = self.rfile.readline()131 if not self.raw_requestline:132 self.close_connection = 1133 return134 135 if not self.parse_request():136 return137 138 response = wsgiApp(self.environ(), self.start_response)139 for chunk in response:140 self.write(chunk)141 except:142 self.handleError(sys.exc_info())143 finally:144 if hasattr(response, 'close'):145 response.close()146 147 def environ(self):148 env = {'wsgi.version': (1, 0),149 'wsgi.input': self.rfile,150 'wsgi.errors': sys.stderr,151 'wsgi.multithread': (cpg.config.get("server.threadPool") > 1),152 'wsgi.multiprocess': False,153 'wsgi.run_once': False,154 'SERVER_PROTOCOL': self.request_version,155 'GATEWAY_INTERFACE': 'CGI/1.1',156 'CONTENT_TYPE': self.headers.get('Content-Type', ''),157 'CONTENT_LENGTH': self.headers.get('Content-Length', ''),158 # SCRIPT_NAME doesn't really apply to CherryPy159 'SCRIPT_NAME': '',160 }161 162 env['SERVER_NAME'] = cpg.config.get('server.socketHost')163 env['SERVER_PORT'] = cpg.config.get('server.socketPort')164 165 if self.os_environ.get("HTTPS") in ('yes', 'on', '1'):166 env['wsgi.url_scheme'] = 'https'167 else:168 env['wsgi.url_scheme'] = 'http'169 170 host, port = self.client_address[:2]171 env['REMOTE_ADDR'] = host172 173 fullhost = socket.getfqdn(host)174 if fullhost == host:175 env['REMOTE_HOST'] = ''176 else:177 env['REMOTE_HOST'] = fullhost178 179 # Update env with results of parse_request180 env['REQUEST_METHOD'] = self.command181 env['SERVER_PROTOCOL'] = self.request_version182 183 if '?' in self.path:184 path, query = self.path.split('?', 1)185 else:186 path, query = self.path, ''187 env['PATH_INFO'] = urllib.unquote(path)188 env['QUERY_STRING'] = query189 190 # Update env with additional request headers191 for name, value in self.headers.items():192 env['HTTP_%s' % name.replace ('-', '_').upper()] = value193 return env194 195 def start_response(self, status, headers, exc_info=None):196 if exc_info:197 try:198 if self.headers_sent:199 raise exc_info[0], exc_info[1], exc_info[2]200 finally:201 # avoid dangling circular ref202 exc_info = None203 elif self.responseHeaders:204 raise AssertionError("Headers already set!")205 self.status = status206 self.responseHeaders = headers[:]207 return self.write208 209 def write(self, data):210 if not self.headers_sent:211 code, reason = self.status.split(" ", 1)212 self.send_response(int(code), reason)213 for name, value in self.responseHeaders:214 self.send_header(name, value)215 self.end_headers()216 self.headers_sent = True217 self.wfile.write(data)218 219 def send_response(self, code, message=None):220 self.log_request(code)221 if message is None:222 if code in self.responses:223 message = self.responses[code][0]224 else:225 message = ''226 if self.request_version != 'HTTP/0.9':227 self.wfile.write("%s %d %s\r\n" %228 (self.protocol_version, code, message))229 230 def handleError(self, exc):231 self.close_connection = 1232 msg = _cphttptools.formatExc(exc)233 _cputil.getSpecialAttribute('_cpLogMessage')(msg, "HTTP")234 self.status, self.headers, body = _cphttptools.bareError()235 self.write(body)236 237 238 119 class WSGIServer(_cpwsgiserver.CherryPyWSGIServer): 239 120 def __init__(self): trunk/cherrypy/test/test_core.py
r320 r339 139 139 140 140 return "double header test" 141 142 143 defined_http_methods = ("OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", 144 "TRACE", "CONNECT") 145 class Method(Test): 146 147 def index(self): 148 m = cpg.request.method 149 if m in defined_http_methods: 150 return m 151 152 if m == "LINK": 153 cpg.response.status = 405 154 else: 155 cpg.response.status = 501 141 156 142 157 … … 243 258 'Location', 'Server']) 244 259 self.assertEqual(cpg.response.body, "double header test") 260 261 def testMethods(self): 262 # Test that all defined HTTP methods work. 263 for m in defined_http_methods: 264 h = [] 265 if m == 'POST': 266 h = [("Content-type", "application/x-www-form-urlencoded"), 267 ("Content-Length", "0")] 268 helper.request("/method/", h, method=m, body='') 269 270 # HEAD requests should not return any body. 271 if m == "HEAD": 272 m = "" 273 274 self.assertEqual(cpg.response.body, m) 275 276 # Request a disallowed method 277 helper.request("/method/", method="LINK") 278 self.assertEqual(cpg.response.status, "405 Method Not Allowed") 279 280 # Request an unknown method 281 helper.request("/method/", method="SEARCH") 282 self.assertEqual(cpg.response.status, "501 Not Implemented") 245 283 246 284

