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

Changeset 1909

Show
Ignore:
Timestamp:
03/07/08 13:47:51
Author:
lakin
Message:

Adding an HTTPRequestSocketWrapper to attempt to solve the non-blocking recvs that are needed.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/598-sendall/cherrypy/wsgiserver/__init__.py

    r1907 r1909  
    234234        self._check_length() 
    235235        return data 
     236 
     237class HTTPRequestSocketWrapper(object): 
     238    """ 
     239    A file like wrapper for HTTP on non-blocking sockets. 
     240 
     241    IOW this class provides as much as it can of the file like  
     242    interface for sockets over which HTTP requests are made. 
     243    """ 
     244    def __init__(self, sock): 
     245        self.sock = sock 
     246        self.incomplete_line_size = 0 
     247        self.incomplete_line_buffer = [] 
     248        self.lines_buffer = [] 
     249     
     250    def read(self, size=None): 
     251        raise NotImplementedError 
     252     
     253    def readline(self, size=None): 
     254        # This doesn't raise the appropriate exceptions 
     255        # as the result may result in an Index Error? 
     256 
     257        # if we can't return their data right away, let's try to read (blocking) 
     258        if not (self.lines_buffer or (size and self.incomplete_line_size >= size)): 
     259            self._fill_lines_buffer() 
     260         
     261        # if we have a complete line to send, use it. 
     262        if self.lines_buffer: 
     263            line = self.lines_buffer[0] 
     264            if size and len(line) > size: 
     265                self.lines_buffer[0] = line[size:] 
     266                line = line[:size] 
     267                return line 
     268            else: 
     269                return self.lines_buffer.pop(0) 
     270 
     271        # If we have enough of a non-complete line to 
     272            # satisfy the size requirement return that. 
     273        elif size and self.incomplete_line_size >= size: 
     274            line = ''.join(self.incomplete_line_buffer) 
     275            new_incomplete_line = line[:size] 
     276            self.incomplete_line_size = len(new_incomplete_line) 
     277            self.incomplete_line_buffer = [new_incomplete_line] 
     278        else: 
     279            assert ("We should never get here, should we?") 
     280             
     281    def _fill_lines_buffer(self, size=None): 
     282        bytes_seen = 0 
     283        while True: 
     284            data = self.sock.recv(256) 
     285            bytes_seen += len(data) 
     286 
     287            lines = data.split("\n") 
     288            # We remove the last piece of the split to ensure 
     289            # that subsequent processing happens only on data 
     290            # Representing complete lines. 
     291            new_incomplete_line = lines.pop() 
     292             
     293            # If we still have data in the lines list that means 
     294            # we have received some data that forms a complete line 
     295            if lines: 
     296                # Ensure that we take the data left over from previous reads 
     297                # and join it to our current reads before appending the latest 
     298                # line seen 
     299                self.incomplete_line_buffer.append(lines.pop(0)) 
     300                self.lines_buffer.append("".join(self.incomplete_line_buffer)) 
     301                self.incomplete_line_size = 0 
     302                self.incomplete_line_buffer = [] 
     303 
     304                # remember all other complete lines seen in this read 
     305                self.lines_buffer.extend(lines) 
     306                
     307            # Record the latest new incomplete line 
     308            if new_incomplete_line: 
     309                self.incomplete_line_size += len(new_incomplete_line) 
     310                self.incomplete_line_buffer.append(new_incomplete_line) 
     311 
     312            # If they didn't specify a size and we have a line to send them 
     313            # stop reading 
     314            if not size and self.lines_buffer: 
     315                return 
     316 
     317            # if we've read over the size that they wanted, then stop reading 
     318            if size and bytes_seen > size: 
     319                return 
     320     
     321    def readlines(self, sizehint=0): 
     322        raise NotImplementedError 
     323     
     324    def close(self): 
     325        self.sock.close() 
     326     
     327    def __iter__(self): 
     328        return self 
     329     
     330    def next(self): 
     331        data = self.sock.next() 
     332        self.bytes_read += len(data) 
     333        return data 
     334 
     335    def send(self, *args, **kwargs): 
     336        return self.sock.send(*args, **kwargs) 
     337 
     338    def readline(self, size=None): 
     339        raise NotImplementedError 
    236340 
    237341 
     
    733837                    raise NoSSLError() 
    734838                raise 
     839            except: 
     840                raise 
    735841            if time.time() - start > self.ssl_timeout: 
    736842                raise socket.timeout("timed out") 
     
    754860        return self._sock.send(*args, **kwargs) 
    755861    send = _ssl_wrap_method(send) 
    756  
    757862 
    758863class HTTPConnection(object): 
     
    787892        if SSL and isinstance(sock, SSL.ConnectionType): 
    788893            timeout = sock.gettimeout() 
    789             self.rfile = SSL_fileobject(sock, "r", self.rbufsize) 
     894            self.rfile = SSL_fileobject(HTTPRequestSocketWrapper(sock), "r", self.rbufsize) 
    790895            self.rfile.ssl_timeout = timeout 
    791896            self.send = self.rfile.send 
    792897        else: 
    793             self.rfile = sock.makefile("rb", self.rbufsize) 
     898            #self.rfile = sock.makefile("rb", self.rbufsize) 
     899            self.rfile = HTTPRequestSocketWrapper(sock) 
    794900            self.send = sock.send 
    795901         
     
    824930            if errnum not in socket_errors_to_ignore: 
    825931                if req: 
     932                    fd = open ("ssl_errors.txt", "a") 
     933                    fd.write("1" * 80) 
     934                    fd.write("\n") 
     935                    fd.write(str(type(e))) 
     936                    fd.write( format_exc()) 
    826937                    req.simple_response("500 Internal Server Error", 
    827938                                        format_exc()) 
     
    835946                                "The client sent a plain HTTP request, but " 
    836947                                "this server only speaks HTTPS on this port.") 
    837         except
     948        except Exception, e
    838949            if req: 
     950                fd = open ("ssl_errors.txt", "a") 
     951                fd.write("2" * 80 ) 
     952                fd.write("\n") 
     953                fd.write(str(type(e))) 
     954                fd.write( format_exc()) 
    839955                req.simple_response("500 Internal Server Error", format_exc()) 
    840956     

Hosted by WebFaction

Log in as guest/cpguest to create tickets