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

Changeset 2272

Show
Ignore:
Timestamp:
05/12/09 15:36:31
Author:
fumanchu
Message:

python3: Fix for #853 (consistent time out of the WSGI server).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/python3/cherrypy/test/test_conn.py

    r2270 r2272  
    247247     
    248248    def test_HTTP11_Timeout(self): 
     249        # If we timeout without sending any data, 
     250        # the server will close the conn with a 408. 
     251        if cherrypy.server.protocol_version != "HTTP/1.1": 
     252            print("skipped ", end=' ') 
     253            return 
     254         
     255        self.PROTOCOL = "HTTP/1.1" 
     256         
     257        # Connect but send nothing. 
     258        self.persistent = True 
     259        conn = self.HTTP_CONN 
     260        conn.auto_open = False 
     261        conn.connect() 
     262         
     263        # Wait for our socket timeout 
     264        time.sleep(timeout * 2) 
     265         
     266        # The request should have returned 408 already. 
     267        response = conn.response_class(conn.sock, method="GET") 
     268        response.begin() 
     269        self.assertEqual(response.status, 408) 
     270        conn.close() 
     271         
     272        # Connect but send half the headers only. 
     273        self.persistent = True 
     274        conn = self.HTTP_CONN 
     275        conn.auto_open = False 
     276        conn.connect() 
     277        conn.send(b'GET /hello HTTP/1.1') 
     278        conn.send(("Host: %s" % self.HOST).encode('ascii')) 
     279         
     280        # Wait for our socket timeout 
     281        time.sleep(timeout * 2) 
     282         
     283        # The conn should have already sent 408. 
     284        response = conn.response_class(conn.sock, method="GET") 
     285        response.begin() 
     286        self.assertEqual(response.status, 408) 
     287        conn.close() 
     288     
     289    def test_HTTP11_Timeout_after_request(self): 
     290        # If we timeout after at least one request has succeeded, 
     291        # the server will close the conn without 408. 
    249292        if cherrypy.server.protocol_version != "HTTP/1.1": 
    250293            print("skipped ", end=' ') 
     
    291334                          " as it should have: %s" % sys.exc_info()[1]) 
    292335        else: 
    293             if response.status != 408: 
    294                 self.fail("Writing to timed out socket didn't fail" 
    295                           " as it should have: %s" % 
    296                           response.read()) 
     336            self.fail("Writing to timed out socket didn't fail" 
     337                      " as it should have: %s" % 
     338                      response.read()) 
    297339         
    298340        conn.close() 
     
    316358        time.sleep(timeout * 2) 
    317359        response = conn.response_class(conn.sock, method="GET") 
    318         response.begin() 
    319         self.assertEqual(response.status, 408) 
     360        try: 
     361            response.begin() 
     362        except: 
     363            if not isinstance(sys.exc_info()[1], 
     364                              (socket.error, http.client.BadStatusLine)): 
     365                self.fail("Writing to timed out socket didn't fail" 
     366                          " as it should have: %s" % sys.exc_info()[1]) 
     367        else: 
     368            self.fail("Writing to timed out socket didn't fail" 
     369                      " as it should have: %s" % 
     370                      response.read()) 
     371         
    320372        conn.close() 
    321373         
  • branches/python3/cherrypy/wsgiserver/__init__.py

    r2270 r2272  
    9090import threading 
    9191import time 
    92 import traceback 
     92from traceback import format_exc 
    9393from urllib.parse import unquote 
    9494from urllib.parse import urlparse 
     
    288288         
    289289        self.ready = False 
     290        self.started_request = False 
    290291        self.started_response = False 
    291292        self.status = "" 
     
    315316        # with FIN_WAIT_2). 
    316317        request_line = self.rfile.readline() 
     318        # Set started_request to True so communicate() knows to send 408 
     319        # from here on out. 
     320        self.started_request = True 
    317321        if not request_line: 
    318322            # Force self.ready = False so the connection will close. 
     
    341345            self.simple_response(400, "Malformed Request-Line") 
    342346            return 
    343         print(repr(request_line)) 
    344347         
    345348        environ["REQUEST_URI"] = path 
     
    420423         
    421424        mrbs = self.max_request_body_size 
    422         print('mrbs', mrbs) 
    423         print('cl', environ.get("CONTENT_LENGTH", 0)) 
    424425        if mrbs and int(environ.get("CONTENT_LENGTH", 0)) > mrbs: 
    425426            self.simple_response("413 Request Entity Too Large") 
     
    536537        if ct is not None: 
    537538            environ["CONTENT_TYPE"] = ct 
    538             print('server ct', ct) 
    539539        cl = environ.pop("HTTP_CONTENT_LENGTH", None) 
    540540        if cl is not None: 
     
    923923    def communicate(self): 
    924924        """Read each request and respond appropriately.""" 
     925        request_seen = False 
    925926        try: 
    926927            while True: 
     
    935936                req.parse_request() 
    936937                if not req.ready: 
     938                    # Something went wrong in the parsing (and the server has 
     939                    # probably already made a simple_response). Return and 
     940                    # let the conn close. 
    937941                    return 
    938942                 
     943                request_seen = True 
    939944                req.respond() 
    940945                if req.close_connection: 
    941946                    return 
    942          
    943947        except socket.error as e: 
    944948            errnum = e.args[0] 
    945949            if errnum == 'timed out': 
    946                 if req and not req.sent_headers: 
    947                     req.simple_response("408 Request Timeout") 
     950                # Don't error if we're between requests; only error 
     951                # if 1) no request has been started at all, or 2) we're 
     952                # in the middle of a request. 
     953                # See http://www.cherrypy.org/ticket/853 
     954                if (not request_seen) or (req and req.started_request): 
     955                    # Don't bother writing the 408 if the response 
     956                    # has already started being written. 
     957                    if req and not req.sent_headers: 
     958                        req.simple_response("408 Request Timeout") 
    948959            elif errnum not in socket_errors_to_ignore: 
    949960                if req and not req.sent_headers: 
     
    9911002            # Apache does, but not today. 
    9921003            pass 
    993  
    994  
    995 def format_exc(limit=None): 
    996     """Like print_exc() but return a string. Backport for Python 2.3.""" 
    997     try: 
    998         etype, value, tb = sys.exc_info() 
    999         return ''.join(traceback.format_exception(etype, value, tb, limit)) 
    1000     finally: 
    1001         etype = value = tb = None 
    10021004 
    10031005 

Hosted by WebFaction

Log in as guest/cpguest to create tickets