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

Changeset 1137

Show
Ignore:
Timestamp:
06/12/06 00:34:44
Author:
fumanchu
Message:

httptools.Version was overengineered. Shame on me. Using tuples gives a 2-3% speed boost.

Files:

Legend:

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

    r1134 r1137  
    7777        # http://ppewww.ph.gla.ac.uk/~flavell/www/post-redirect.html 
    7878        if status is None: 
    79             if cherrypy.response.version >= "1.1"
     79            if cherrypy.response.version >= (1, 1)
    8080                status = 303 
    8181            else: 
  • trunk/cherrypy/_cprequest.py

    r1136 r1137  
    220220         
    221221        # cherrypy.request.version == request.protocol in a Version instance. 
    222         self.version = httptools.Version.from_http(self.protocol) 
     222        self.version = httptools.version_from_http(self.protocol) 
    223223         
    224224        # cherrypy.response.version should be used to determine whether or 
    225225        # not to include a given HTTP/1.1 feature in the response content. 
    226226        server_v = cherrypy.config.get('server.protocol_version', 'HTTP/1.0') 
    227         server_v = httptools.Version.from_http(server_v) 
     227        server_v = httptools.version_from_http(server_v) 
    228228        cherrypy.response.version = min(self.version, server_v) 
    229229     
     
    244244                self.simple_cookie.load(value) 
    245245         
    246         if self.version >= "1.1": 
     246        host = self.headers.get('Host') 
     247        if host is None: 
    247248            # All Internet-based HTTP/1.1 servers MUST respond with a 400 
    248249            # (Bad Request) status code to any HTTP/1.1 request message 
    249250            # which lacks a Host header field. 
    250             if not self.headers.has_key("Host"): 
     251            if self.version >= (1, 1): 
    251252                msg = "HTTP/1.1 requires a 'Host' request header." 
    252253                raise cherrypy.HTTPError(400, msg) 
    253          
    254         host = self.headers.get('Host', '') 
    255254        if not host: 
    256255            host = cherrypy.config.get('server.socket_host', '') 
  • trunk/cherrypy/lib/httptools.py

    r1125 r1137  
    1 """HTTP library functions and tools.""" 
    2  
    3 # This module contains functions and tools for building an HTTP application 
     1"""HTTP library functions.""" 
     2 
     3# This module contains functions for building an HTTP application 
    44# framework: any one, not just one whose name starts with "Ch". ;) If you 
    55# reference any modules from some popular framework inside *this* module, 
     
    2323import re 
    2424import time 
    25 import urllib 
     25from urllib import unquote 
    2626from urlparse import urlparse 
    2727 
     
    6363 
    6464 
    65 class Version(object): 
    66      
    67     """A version, such as "2.1 beta 3", which can be compared atom-by-atom. 
    68      
    69     If a string is provided to the constructor, it will be split on word 
    70     boundaries; that is, "1.4.13 beta 9" -> ["1", "4", "13", "beta", "9"]. 
    71      
    72     Comparisons are performed atom-by-atom, numerically if both atoms are 
    73     numeric. Therefore, "2.12" is greater than "2.4", and "3.0 beta" is 
    74     greater than "3.0 alpha" (only because "b" > "a"). If an atom is 
    75     provided in one Version and not another, the longer Version is 
    76     greater than the shorter, that is: "4.8 alpha" > "4.8". 
    77     """ 
    78      
    79     def __init__(self, atoms): 
    80         """A Version object. 
    81          
    82         atoms: if a str, it will be split on word boundaries; 
    83                if a float or int, it will be split at the decimal point. 
    84         """ 
    85         if isinstance(atoms, (int, float)): 
    86             atoms = str(atoms) 
    87         if isinstance(atoms, basestring): 
    88             self.atoms = re.split(r'\W', atoms) 
    89         else: 
    90             self.atoms = [str(x) for x in atoms] 
    91      
    92     def from_http(cls, version_str): 
    93         """Return a Version object from the given 'HTTP/x.y' string.""" 
    94         return cls(version_str[5:]) 
    95     from_http = classmethod(from_http) 
    96      
    97     def to_http(self): 
    98         """Return a 'HTTP/x.y' string for this Version object.""" 
    99         return "HTTP/%s.%s" % tuple(self.atoms[:2]) 
    100      
    101     def __str__(self): 
    102         return ".".join([str(x) for x in self.atoms]) 
    103      
    104     def __cmp__(self, other): 
    105         cls = self.__class__ 
    106         if not isinstance(other, cls): 
    107             # Try to coerce other to a Version instance. 
    108             other = cls(other) 
    109          
    110         index = 0 
    111         while index < len(self.atoms) and index < len(other.atoms): 
    112             mine, theirs = self.atoms[index], other.atoms[index] 
    113             if mine.isdigit() and theirs.isdigit(): 
    114                 mine, theirs = int(mine), int(theirs) 
    115             if mine < theirs: 
    116                 return -1 
    117             if mine > theirs: 
    118                 return 1 
    119             index += 1 
    120         if index < len(other.atoms): 
    121             return -1 
    122         if index < len(self.atoms): 
    123             return 1 
    124         return 0 
    125  
     65def version_from_http(version_str): 
     66    """Return a Version tuple from the given 'HTTP/x.y' string.""" 
     67    return int(version_str[5]), int(version_str[7]) 
    12668 
    12769def getRanges(headervalue, content_length): 
     
    318260    # [Therefore, this assumes all hosts are valid for this server. 
    319261    # Note that we are also violating the RFC which says: if the host 
    320     # given in an abs_path, it must override any Host header.] 
     262    # given is an abs_path, it must override any Host header.] 
    321263    scheme, location, path, params, qs, frag = urlparse(path) 
    322     if path == "*": 
    323         # "...the request does not apply to a particular resource, 
    324         # but to the server itself". See 
    325         # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 
    326         pass 
    327     else: 
    328         if params: 
    329             params = ";" + params 
    330         path = path + params 
    331          
    332         # Unquote the path (e.g. "/this%20path" -> "this path"). 
    333         # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 
    334         # 
    335         # But note that "...a URI must be separated into its components 
    336         # before the escaped characters within those components can be 
    337         # safely decoded." http://www.ietf.org/rfc/rfc2396.txt, sec 2.4.2 
    338         # 
    339         # Note also that cgi.parse_qs will decode the querystring for us. 
    340         atoms = [urllib.unquote(x) for x in re.split("(?i)%2F", path)] 
    341         path = "%2F".join(atoms) 
     264     
     265    if params: 
     266        path = path + ";" + params 
     267     
     268    # Unquote the path (e.g. "/this%20path" -> "this path"). 
     269    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 
     270    # 
     271    # But note that "...a URI must be separated into its components 
     272    # before the escaped characters within those components can be 
     273    # safely decoded." http://www.ietf.org/rfc/rfc2396.txt, sec 2.4.2 
     274    # 
     275    # Note also that cgi.parse_qs will decode the querystring for us. 
     276    atoms = [unquote(x) for x in re.split("(?i)%2F", path)] 
     277    path = "%2F".join(atoms) 
    342278     
    343279    return method, path, qs, protocol 
  • trunk/cherrypy/lib/static.py

    r1117 r1137  
    7575     
    7676    # HTTP/1.0 didn't have Range/Accept-Ranges headers, or the 206 code 
    77     if cherrypy.response.version >= "1.1"
     77    if cherrypy.response.version >= (1, 1)
    7878        response.headers["Accept-Ranges"] = "bytes" 
    7979        r = httptools.getRanges(cherrypy.request.headers.get('Range'), c_len) 
  • trunk/cherrypy/lib/wsgiapp.py

    r1114 r1137  
    3131    environ["PATH_INFO"] = cherrypy.request.path_info 
    3232    environ["QUERY_STRING"] = cherrypy.request.query_string 
    33     environ["SERVER_PROTOCOL"] = cherrypy.request.version 
     33    environ["SERVER_PROTOCOL"] = cherrypy.request.protocol 
    3434    server_name = getattr(cherrypy.server.httpserver, 'server_name', "None") 
    3535    environ["SERVER_NAME"] = server_name  

Hosted by WebFaction

Log in as guest/cpguest to create tickets