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

Changeset 1263

Show
Ignore:
Timestamp:
08/21/06 16:06:43
Author:
fumanchu
Message:

Fixed the HTTP/1.0 test suite. This involved moving wsgi SERVER_PROTOCOL back (to what the spec says!) and adding a new non-standard ACTUAL_SERVER_PROTOCOL entry.

Files:

Legend:

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

    r1246 r1263  
    190190                                    " receive requests, False otherwise.") 
    191191     
    192     def request(self, local_host, remote_host, scheme="http"): 
     192    def request(self, local_host, remote_host, scheme="http", 
     193                server_protocol="HTTP/1.1"): 
    193194        """Obtain an HTTP Request object. 
    194195         
     
    210211                for func in self.on_start_thread_list: 
    211212                    func(i) 
    212             req = self.request_class(local_host, remote_host, scheme) 
     213            req = self.request_class(local_host, remote_host, scheme, 
     214                                     server_protocol) 
    213215        cherrypy.serving.request = req 
    214216        cherrypy.serving.response = resp = self.response_class() 
  • trunk/cherrypy/_cprequest.py

    r1261 r1263  
    8282    remote = http.Host("localhost", 1111) 
    8383    scheme = "http" 
     84    server_protocol = "HTTP/1.1" 
    8485    base = "" 
    8586     
     
    115116    hooks = HookMap(hookpoints) 
    116117     
    117     def __init__(self, local_host, remote_host, scheme="http"): 
     118    def __init__(self, local_host, remote_host, scheme="http", 
     119                 server_protocol="HTTP/1.1"): 
    118120        """Populate a new Request object. 
    119121         
     
    125127        self.remote = remote_host 
    126128        self.scheme = scheme 
     129        self.server_protocol = server_protocol 
    127130         
    128131        self.closed = False 
     
    142145            cherrypy.serving.__dict__.clear() 
    143146     
    144     def run(self, method, path, query_string, protocol, headers, rfile): 
     147    def run(self, method, path, query_string, req_protocol, headers, rfile): 
    145148        """Process the Request. 
    146149         
    147         method, path, query_string, and protocol should be pulled directly 
     150        method, path, query_string, and req_protocol should be pulled directly 
    148151            from the Request-Line (e.g. "GET /path?key=val HTTP/1.0"). 
    149152        path should be %XX-unquoted, but query_string should not be. 
     
    160163         
    161164        """ 
     165         
    162166        try: 
    163167            self.error_response = cherrypy.HTTPError(500).set_response 
     
    166170            self.path = path or "/" 
    167171            self.query_string = query_string 
    168             self.protocol = int(protocol[5]), int(protocol[7]) 
     172             
     173            # Compare request and server HTTP protocol versions, in case our 
     174            # server does not support the requested protocol. Limit our output 
     175            # to min(req, server). We want the following output: 
     176            #     request    server     actual written   supported response 
     177            #     protocol   protocol  response protocol    feature set 
     178            # a     1.0        1.0           1.0                1.0 
     179            # b     1.0        1.1           1.1                1.0 
     180            # c     1.1        1.0           1.0                1.0 
     181            # d     1.1        1.1           1.1                1.1 
     182            # Notice that, in (b), the response will be "HTTP/1.1" even though 
     183            # the client only understands 1.0. RFC 2616 10.5.6 says we should 
     184            # only return 505 if the _major_ version is different. 
     185            rp = int(req_protocol[5]), int(req_protocol[7]) 
     186            sp = int(self.server_protocol[5]), int(self.server_protocol[7]) 
     187            self.protocol = min(rp, sp) 
    169188             
    170189            # Rebuild first line of the request (e.g. "GET /path HTTP/1.0"). 
     
    172191            if query_string: 
    173192                url += '?' + query_string 
    174             self.request_line = '%s %s %s' % (method, url, protocol) 
     193            self.request_line = '%s %s %s' % (method, url, req_protocol) 
    175194             
    176195            self.header_list = list(headers) 
  • trunk/cherrypy/_cpwsgi.py

    r1260 r1263  
    3636                           int(env('REMOTE_PORT', -1)), 
    3737                           env('REMOTE_HOST', '')) 
    38         request = cherrypy.engine.request(local, remote, env('wsgi.url_scheme')) 
     38        request = cherrypy.engine.request(local, remote, 
     39                                          env('wsgi.url_scheme'), 
     40                                          env('ACTUAL_SERVER_PROTOCOL', None)) 
    3941         
    4042        # LOGON_USER is served by IIS, and is the name of the 
  • trunk/cherrypy/_cpwsgiserver.py

    r1259 r1263  
    111111        # to min(req, server). We want the following output: 
    112112        #     request    server     actual written   supported response 
    113         #     protocol   protocol  response protocol feature set (SERVER_PROTOCOL) 
     113        #     protocol   protocol  response protocol    feature set 
    114114        # a     1.0        1.0           1.0                1.0 
    115115        # b     1.0        1.1           1.1                1.0 
     
    124124            self.simple_response("505 HTTP Version Not Supported") 
    125125            return 
    126         self.environ["SERVER_PROTOCOL"] = "HTTP/%s.%s" % min(rp, sp) 
     126        # Bah. "SERVER_PROTOCOL" is actually the REQUEST protocol. 
     127        self.environ["SERVER_PROTOCOL"] = req_protocol 
     128        # set a non-standard environ entry so the WSGI app can know what 
     129        # the *real* server protocol is (and what features to support). 
     130        self.environ["ACTUAL_SERVER_PROTOCOL"] = server.protocol 
     131        self.response_protocol = "HTTP/%s.%s" % min(rp, sp) 
    127132         
    128133        # If the Request-URI was an absoluteURI, use its location atom. 
     
    145150         
    146151        # Persistent connection support 
    147         if self.environ["SERVER_PROTOCOL"] == "HTTP/1.1": 
     152        if self.response_protocol == "HTTP/1.1": 
    148153            if headers.getheader("Connection", "") == "close": 
    149154                self.close_connection = True 
     
    247252        wfile.write("Content-Length: %s\r\n" % len(msg)) 
    248253         
    249         if status[:3] == "413" and self.environ["SERVER_PROTOCOL"] == 'HTTP/1.1': 
     254        if status[:3] == "413" and self.response_protocol == 'HTTP/1.1': 
    250255            # Request Entity Too Large 
    251256            self.close_connection = True 
     
    281286        hkeys = [key.lower() for (key,value) in self.outheaders] 
    282287         
    283         if (self.environ["SERVER_PROTOCOL"] == 'HTTP/1.1' 
     288        if (self.response_protocol == 'HTTP/1.1' 
    284289            and (# Request Entity Too Large. Close conn to avoid garbage. 
    285290                self.status[:3] == "413" 
  • trunk/cherrypy/test/test.py

    r1262 r1263  
    3636        print "Python version used to run this test script:", v 
    3737        print "CherryPy version", cherrypy.__version__ 
     38        print "HTTP server version", self.protocol 
    3839        print 
    3940         
  • trunk/cherrypy/test/test_caching.py

    r1215 r1263  
    125125        # This also gives us a chance to test 0 expiry with no other headers 
    126126        self.assertHeader("Pragma", "no-cache") 
    127         self.assertHeader("Cache-Control", "no-cache") 
     127        if cherrypy.config.get('server.protocol_version') == "HTTP/1.1": 
     128            self.assertHeader("Cache-Control", "no-cache") 
    128129        d = self.assertHeader("Date") 
    129130        self.assertHeader("Expires", d) 
     
    133134        self.assertStatus("200 OK") 
    134135        self.assertHeader("Pragma", "no-cache") 
    135         self.assertHeader("Cache-Control", "no-cache") 
     136        if cherrypy.config.get('server.protocol_version') == "HTTP/1.1": 
     137            self.assertHeader("Cache-Control", "no-cache") 
    136138        d = self.assertHeader("Date") 
    137139        self.assertHeader("Expires", d) 
     
    141143        self.assertStatus("200 OK") 
    142144        self.assertHeader("Pragma", "no-cache") 
    143         self.assertHeader("Cache-Control", "no-cache") 
     145        if cherrypy.config.get('server.protocol_version') == "HTTP/1.1": 
     146            self.assertHeader("Cache-Control", "no-cache") 
    144147        d = self.assertHeader("Date") 
    145148        self.assertHeader("Expires", d) 
     
    150153        # overwritten here ... 
    151154        self.assertHeader("Pragma", "no-cache") 
    152         self.assertHeader("Cache-Control", "no-cache") 
     155        if cherrypy.config.get('server.protocol_version') == "HTTP/1.1": 
     156            self.assertHeader("Cache-Control", "no-cache") 
    153157        d = self.assertHeader("Date") 
    154158        self.assertHeader("Expires", d) 
  • trunk/cherrypy/test/test_conn.py

    r1259 r1263  
    5151     
    5252    def test_HTTP11(self): 
     53        if cherrypy.config.get('server.protocol_version') != "HTTP/1.1": 
     54            print "skipped ", 
     55            return 
     56         
    5357        self.PROTOCOL = "HTTP/1.1" 
    5458         
     
    8993     
    9094    def test_HTTP11_pipelining(self): 
     95        if cherrypy.config.get('server.protocol_version') != "HTTP/1.1": 
     96            print "skipped ", 
     97            return 
     98         
    9199        self.PROTOCOL = "HTTP/1.1" 
    92100         
     
    123131     
    124132    def test_100_Continue(self): 
     133        if cherrypy.config.get('server.protocol_version') != "HTTP/1.1": 
     134            print "skipped ", 
     135            return 
     136         
    125137        self.PROTOCOL = "HTTP/1.1" 
    126138         
     
    171183     
    172184    def test_Chunked_Encoding(self): 
     185        if cherrypy.config.get('server.protocol_version') != "HTTP/1.1": 
     186            print "skipped ", 
     187            return 
     188         
    173189        self.PROTOCOL = "HTTP/1.1" 
    174190         
  • trunk/cherrypy/test/test_core.py

    r1259 r1263  
    373373        'log_to_screen': False, 
    374374        'log_file': log_file, 
    375         'server.protocol_version': "HTTP/1.1", 
    376375        'environment': 'production', 
    377376        'show_tracebacks': True, 
     
    469468        line = data[-2].strip() 
    470469        if haslength: 
    471             self.assert_(line.endswith('] "GET %s/flatten/as_string HTTP/1.1" 200 7 "" ""' 
    472                                           % self.prefix())) 
     470            if not line.endswith('] "GET %s/flatten/as_string HTTP/1.1" 200 7 "" ""' 
     471                                 % self.prefix()): 
     472                self.fail(line) 
    473473        else: 
    474             self.assert_(line.endswith('] "GET %s/flatten/as_string HTTP/1.1" 200 - "" ""' 
    475                                           % self.prefix())) 
     474            if not line.endswith('] "GET %s/flatten/as_string HTTP/1.1" 200 - "" ""' 
     475                                 % self.prefix()): 
     476                self.fail(line) 
    476477         
    477478        self.assertEqual(data[-1][:15], '127.0.0.1 - - [') 
     
    586587        self.assertStatus(200) 
    587588        self.assertBody("(['http://127.0.0.1:%s/'], 302)" % self.PORT) 
    588         self.getPage("/redirect/stringify", protocol="HTTP/1.1") 
    589         self.assertStatus(200) 
    590         self.assertBody("(['http://127.0.0.1:%s/'], 303)" % self.PORT) 
     589        if cherrypy.config.get('server.protocol_version') == "HTTP/1.1": 
     590            self.getPage("/redirect/stringify", protocol="HTTP/1.1") 
     591            self.assertStatus(200) 
     592            self.assertBody("(['http://127.0.0.1:%s/'], 303)" % self.PORT) 
    591593     
    592594    def testFlatten(self): 
     
    653655         
    654656        # Get a partial file. 
    655         self.getPage("/ranges/slice_file", [('Range', 'bytes=2-5')]) 
    656         self.assertStatus(206) 
    657         self.assertHeader("Content-Type", "text/html") 
    658         self.assertHeader("Content-Range", "bytes 2-5/14") 
    659         self.assertBody("llo,") 
    660          
    661         # What happens with overlapping ranges (and out of order, too)? 
    662         self.getPage("/ranges/slice_file", [('Range', 'bytes=4-6,2-5')]) 
    663         self.assertStatus(206) 
    664         ct = "" 
    665         for k, v in self.headers: 
    666             if k.lower() == "content-type": 
    667                 ct = v 
    668                 break 
    669         expected_type = "multipart/byteranges; boundary=" 
    670         self.assert_(ct.startswith(expected_type)) 
    671         boundary = ct[len(expected_type):] 
    672         expected_body = """--%s 
     657        if cherrypy.config.get('server.protocol_version') == "HTTP/1.1": 
     658            self.getPage("/ranges/slice_file", [('Range', 'bytes=2-5')]) 
     659            self.assertStatus(206) 
     660            self.assertHeader("Content-Type", "text/html") 
     661            self.assertHeader("Content-Range", "bytes 2-5/14") 
     662            self.assertBody("llo,") 
     663             
     664            # What happens with overlapping ranges (and out of order, too)? 
     665            self.getPage("/ranges/slice_file", [('Range', 'bytes=4-6,2-5')]) 
     666            self.assertStatus(206) 
     667            ct = "" 
     668            for k, v in self.headers: 
     669                if k.lower() == "content-type": 
     670                    ct = v 
     671                    break 
     672            expected_type = "multipart/byteranges; boundary=" 
     673            self.assert_(ct.startswith(expected_type)) 
     674            boundary = ct[len(expected_type):] 
     675            expected_body = """--%s 
    673676Content-type: text/html 
    674677Content-range: bytes 4-6/14 
     
    681684llo,  
    682685--%s""" % (boundary, boundary, boundary) 
    683         self.assertBody(expected_body) 
    684         self.assertHeader("Content-Length") 
    685          
    686         # Test "416 Requested Range Not Satisfiable" 
    687         self.getPage("/ranges/slice_file", [('Range', 'bytes=2300-2900')]) 
    688         self.assertStatus(416) 
    689         self.assertHeader("Content-Range", "bytes */14") 
    690          
    691         # Test Range behavior with HTTP/1.0 request 
    692         self.getPage("/ranges/slice_file", [('Range', 'bytes=2-5')], protocol="HTTP/1.0"
    693         self.assertStatus(200) 
    694         self.assertBody("Hello, world\r\n") 
     686            self.assertBody(expected_body) 
     687            self.assertHeader("Content-Length") 
     688             
     689            # Test "416 Requested Range Not Satisfiable" 
     690            self.getPage("/ranges/slice_file", [('Range', 'bytes=2300-2900')]) 
     691            self.assertStatus(416) 
     692            self.assertHeader("Content-Range", "bytes */14") 
     693        elif cherrypy.config.get('server.protocol_version') == "HTTP/1.0": 
     694            # Test Range behavior with HTTP/1.0 request 
     695            self.getPage("/ranges/slice_file", [('Range', 'bytes=2-5')]
     696            self.assertStatus(200) 
     697            self.assertBody("Hello, world\r\n") 
    695698     
    696699    def testExpect(self): 
     
    759762            self.assertEqual(hnames.count(key), 1) 
    760763         
    761         # Test RFC-2047-encoded request and response header values 
    762         self.getPage("/headers/ifmatch", 
    763                      [('If-Match', '=?utf-8?q?=E2=84=ABngstr=C3=B6m?=')]) 
    764         self.assertBody("u'\\u212bngstr\\xf6m'") 
    765         self.assertHeader("ETag", '=?utf-8?b?4oSrbmdzdHLDtm0=?=') 
    766          
    767         # Test a *LONG* RFC-2047-encoded request and response header value 
    768         c = "=E2=84=ABngstr=C3=B6m" 
    769         self.getPage("/headers/ifmatch", 
    770                      [('If-Match', '=?utf-8?q?%s?=' % (c * 10))]) 
    771         self.assertBody("u'%s'" % ('\\u212bngstr\\xf6m' * 10)) 
    772         self.assertHeader("ETag", 
    773                           '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt4oSrbmdzdHLDtm0=?=' 
    774                           '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt4oSrbmdzdHLDtm0=?=' 
    775                           '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2bQ==?=') 
     764        if cherrypy.config.get('server.protocol_version') == "HTTP/1.1": 
     765            # Test RFC-2047-encoded request and response header values 
     766            self.getPage("/headers/ifmatch", 
     767                         [('If-Match', '=?utf-8?q?=E2=84=ABngstr=C3=B6m?=')]) 
     768            self.assertBody("u'\\u212bngstr\\xf6m'") 
     769            self.assertHeader("ETag", '=?utf-8?b?4oSrbmdzdHLDtm0=?=') 
     770             
     771            # Test a *LONG* RFC-2047-encoded request and response header value 
     772            c = "=E2=84=ABngstr=C3=B6m" 
     773            self.getPage("/headers/ifmatch", 
     774                         [('If-Match', '=?utf-8?q?%s?=' % (c * 10))]) 
     775            self.assertBody("u'%s'" % ('\\u212bngstr\\xf6m' * 10)) 
     776            self.assertHeader("ETag", 
     777                              '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt4oSrbmdzdHLDtm0=?=' 
     778                              '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2beKEq25nc3Ryw7Zt4oSrbmdzdHLDtm0=?=' 
     779                              '=?utf-8?b?4oSrbmdzdHLDtm3ihKtuZ3N0csO2bQ==?=') 
    776780         
    777781        # Test that two request headers are collapsed into one. 

Hosted by WebFaction

Log in as guest/cpguest to create tickets