Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1563

Show
Ignore:
Timestamp:
12/23/06 15:06:17
Author:
fumanchu
Message:

wsgiserver: replaced rfc822.Message + parse_headers method with a single read_headers method. This saves a pass on parsing headers (as well as a lot of lower() calls and such).

benchmark: removed InternalRedirect? from pipeline.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/test/benchmark.py

    r1562 r1563  
    9999        }, 
    100100    } 
    101 cherrypy.tree.mount(Root(), SCRIPT_NAME, appconf) 
     101app = cherrypy.tree.mount(Root(), SCRIPT_NAME, appconf) 
     102# Remove internalredirect (nastily on by default) 
     103app.wsgiapp.pipeline = [] 
    102104 
    103105 
  • trunk/cherrypy/wsgiserver.py

    r1562 r1563  
    141141         
    142142        server = self.connection.server 
    143         self.environ["SERVER_SOFTWARE"] = "%s WSGI Server" % server.version 
     143        environ = self.environ 
     144        environ["SERVER_SOFTWARE"] = "%s WSGI Server" % server.version 
    144145         
    145146        method, path, req_protocol = request_line.strip().split(" ", 2) 
    146         self.environ["REQUEST_METHOD"] = method 
     147        environ["REQUEST_METHOD"] = method 
    147148         
    148149        # path may be an abs_path (including "http://host.domain.tld"); 
     
    155156         
    156157        if scheme: 
    157             self.environ["wsgi.url_scheme"] = scheme 
     158            environ["wsgi.url_scheme"] = scheme 
    158159        if params: 
    159160            path = path + ";" + params 
     
    171172            # This means, of course, that the last wsgi_app (shortest path) 
    172173            # will always handle a URI of "*". 
    173             self.environ["SCRIPT_NAME"] = "" 
    174             self.environ["PATH_INFO"] = "*" 
     174            environ["SCRIPT_NAME"] = "" 
     175            environ["PATH_INFO"] = "*" 
    175176            self.wsgi_app = server.mount_points[-1][1] 
    176177        else: 
     
    178179                # The mount_points list should be sorted by length, descending. 
    179180                if path.startswith(mount_point + "/") or path == mount_point: 
    180                     self.environ["SCRIPT_NAME"] = mount_point 
    181                     self.environ["PATH_INFO"] = path[len(mount_point):] 
     181                    environ["SCRIPT_NAME"] = mount_point 
     182                    environ["PATH_INFO"] = path[len(mount_point):] 
    182183                    self.wsgi_app = wsgi_app 
    183184                    break 
     
    188189        # Note that, like wsgiref and most other WSGI servers, 
    189190        # we unquote the path but not the query string. 
    190         self.environ["QUERY_STRING"] = qs 
     191        environ["QUERY_STRING"] = qs 
    191192         
    192193        # Compare request and server HTTP protocol versions, in case our 
     
    208209            return 
    209210        # Bah. "SERVER_PROTOCOL" is actually the REQUEST protocol. 
    210         self.environ["SERVER_PROTOCOL"] = req_protocol 
     211        environ["SERVER_PROTOCOL"] = req_protocol 
    211212        # set a non-standard environ entry so the WSGI app can know what 
    212213        # the *real* server protocol is (and what features to support). 
    213214        # See http://www.faqs.org/rfcs/rfc2145.html. 
    214         self.environ["ACTUAL_SERVER_PROTOCOL"] = server.protocol 
     215        environ["ACTUAL_SERVER_PROTOCOL"] = server.protocol 
    215216        self.response_protocol = "HTTP/%s.%s" % min(rp, sp) 
    216217         
    217218        # If the Request-URI was an absoluteURI, use its location atom. 
    218219        if location: 
    219             self.environ["SERVER_NAME"] = location 
     220            environ["SERVER_NAME"] = location 
    220221         
    221222        # then all the http headers 
    222         headers = rfc822.Message(self.rfile, seekable=0) 
    223         self.environ.update(self.parse_headers(headers)) 
    224          
    225         creds = headers.getheader("Authorization", "").split(" ", 1) 
    226         self.environ["AUTH_TYPE"] = creds[0] 
     223        try: 
     224            self.read_headers() 
     225        except ValueError, ex: 
     226            self.simple_response("400 Bad Request", repr(ex.args)) 
     227            return 
     228         
     229        creds = environ.get("HTTP_AUTHORIZATION", "").split(" ", 1) 
     230        environ["AUTH_TYPE"] = creds[0] 
    227231        if creds[0].lower() == 'basic': 
    228232            user, pw = base64.decodestring(creds[1]).split(":", 1) 
    229             self.environ["REMOTE_USER"] = user 
     233            environ["REMOTE_USER"] = user 
    230234         
    231235        # Persistent connection support 
    232236        if self.response_protocol == "HTTP/1.1": 
    233             if headers.getheader("Connection", "") == "close": 
     237            if environ.get("HTTP_CONNECTION", "") == "close": 
    234238                self.close_connection = True 
    235239                self.outheaders.append(("Connection", "close")) 
    236240        else: 
    237241            # HTTP/1.0 
    238             if headers.getheader("Connection", "") == "Keep-Alive": 
     242            if environ.get("HTTP_CONNECTION", "") == "Keep-Alive": 
    239243                if self.close_connection == False: 
    240244                    self.outheaders.append(("Connection", "Keep-Alive")) 
     
    243247         
    244248        # Transfer-Encoding support 
    245         te = headers.getheader("Transfer-Encoding", "") 
     249        te = environ.get("HTTP_TRANSFER_ENCODING", "") 
    246250        te = [x.strip() for x in te.split(",") if x.strip()] 
    247251        if te: 
     
    256260                    return 
    257261        else: 
    258             cl = headers.getheader("Content-length") 
     262            cl = environ.get("CONTENT_LENGTH") 
    259263            if method in ("POST", "PUT") and cl is None: 
    260264                # No Content-Length header supplied. This will hang 
     
    282286        # We used to do 3, but are now doing 1. Maybe we'll do 2 someday, 
    283287        # but it seems like it would be a big slowdown for such a rare case. 
    284         if headers.getheader("Expect", "") == "100-continue": 
     288        if environ.get("HTTP_EXPECT", "") == "100-continue": 
    285289            self.simple_response(100) 
    286290         
    287291        self.ready = True 
    288292     
    289     def parse_headers(self, headers): 
    290         """Parse the given HTTP request message-headers.""" 
    291         environ = {} 
    292         ct = headers.dict.get("content-type") 
    293         if ct: 
    294             environ["CONTENT_TYPE"] = ct 
    295         cl = headers.dict.get("content-length") 
    296         if cl: 
    297             environ["CONTENT_LENGTH"] = cl 
    298          
    299         for line in headers.headers: 
    300             if line[:1].isspace(): 
     293    def read_headers(self): 
     294        """Read header lines from the incoming stream.""" 
     295        environ = self.environ 
     296         
     297        while True: 
     298            line = self.rfile.readline() 
     299            if not line: 
     300                # No more data--illegal end of headers 
     301                raise ValueError("Illegal end of headers.") 
     302             
     303            if line == '\r\n': 
     304                # Normal end of headers 
     305                break 
     306             
     307            if line[0] in ' \t': 
     308                # It's a continuation line. 
    301309                v = line.strip() 
    302310            else: 
     
    311319            environ[envname] = v 
    312320         
    313         return environ 
     321        ct = environ.pop("HTTP_CONTENT_TYPE", None) 
     322        if ct: 
     323            environ["CONTENT_TYPE"] = ct 
     324        cl = environ.pop("HTTP_CONTENT_LENGTH", None) 
     325        if cl: 
     326            environ["CONTENT_LENGTH"] = cl 
    314327     
    315328    def decode_chunked(self): 
     
    333346         
    334347        # Grab any trailer headers 
    335         headers = rfc822.Message(self.rfile, seekable=0) 
    336         self.environ.update(self.parse_headers(headers)) 
     348        self.read_headers() 
    337349         
    338350        data.seek(0) 

Hosted by WebFaction

Log in as guest/cpguest to create tickets