Changeset 741

Show
Ignore:
Timestamp:
07/08/07 12:08:54 (2 years ago)
Author:
robin
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • asycamore/trunk/asycamore/asycwsgi.py

    r738 r741  
    3737 
    3838    httpservice.update_log_config() 
    39     httpservicecontext.update_log_config() 
    40  
    4139 
    4240    asycamore = __import__('asycamore.dispatch_' + opts.dispatcher) 
  • asycamore/trunk/asycamore/httpservicecontext.py

    r738 r741  
    1 import sys, logging 
     1import sys, time, logging 
    22from itertools import chain 
    33from collections import deque 
     4 
    45import asycamore.tcpsocket as tcpsocket 
     6import asycamore.chunkedtransfer as chunkedtransfer 
     7import asycamore.requestresponse as requestresponse 
    58import asycamore.wsgienviron as wsgienviron 
    6 import asycamore.chunkedtransfer as chunkedtransfer 
    7  
    8 import asycamore.requestresponse as requestresponse 
     9import asycamore.wsgistreams as wsgistreams 
    910 
    1011log = logging.getLogger(__name__) 
    11 loginfo = log.info 
    1212logdebug = log.debug 
    1313 
     
    234234 
    235235 
    236     def create_response_context(self, d): 
     236    def create_response_context(self, d, use_asycamore_input=False): 
    237237 
    238238        if self.close_after_current is True: 
     
    276276 
    277277        environ['asycamore.response_headers'] = response_headers 
    278         environ['asycamore.input_read'] = self._input_read 
    279278        environ['asycamore.read_sentinel'] = self.read_sentinel 
    280279        environ['asycamore.deferred_sentinel'] = self.deferred_sentinel 
     
    286285        if cl > 0: 
    287286            self.content_pending = cl 
     287        if not use_asycamore_input: 
     288            return [False, environ] 
     289 
     290        environ['asycamore.input_read'] = self._input_read 
    288291        if read_chunked: 
    289292            self.content_pending = True 
     
    291294            chunker.next() 
    292295            environ['asycamore.input_chunker' 
    293                     ] = self._input_chunker(chunker, environ) 
    294  
     296                    ] = self._input_chunker(chunker, environ)  
    295297        return [False, environ] 
    296298 
     
    515517        tstart = time.time() 
    516518 
     519        # XXX: Ok, yes, this is not pleasant. I promise to improve the api. 
     520        #  - Probably by hiding the perverse control flow from the application, 
     521        # at the expense of some flexibility. 
     522 
    517523        def resultback(result): 
    518524            # tit about because we lack chunked responses for now. 
     
    564570 
    565571    def start_request(self, d): 
    566  
    567         v = self.create_response_context(d) 
     572        """Start the request in the current thread. 
     573 
     574        The environ provided to applications by this method is *not* fully 
     575        conformant with pep-333. The `wsgi.input` attribute breaks the standard 
     576        established in pep-333 in order to allow for asynchronous reads. 
     577 
     578        Instead of calling ``environ['wsgi.input'].read`` or readlines, 
     579        applications simply iterate over the `wsgi.input` attribute. Each value 
     580        yielded will be either raw data read from the connection or the 
     581        ``environ['asycamore.read_sentinel]``. 
     582 
     583        If the read_sentinel is encountered then the next yield from the 
     584        application is *required* to be the read_sentinel. A simple example 
     585        of an application that is compatible with this `start_request` and 
     586        its associated `environ` semantics:: 
     587 
     588            inp = environ['wsgi.input'] 
     589            sentinel = environ['asycamore.read_sentinel'] 
     590            for v in inp: 
     591                if v is sentinel: 
     592                    yield v 
     593                else: 
     594                    response_part = process_content(v) 
     595                    yield response_part 
     596 
     597            # If it has more response data, then it keeps going 
     598            while 1: 
     599                # next_response_part is assumed to raise StopIteration 
     600                # when its exhausted. 
     601                yield next_response_part() 
     602 
     603        The application is completely responsible for parsing the data produced 
     604        by the `input` iterable. For form processing using cgi.FieldStorage it 
     605        is required to deal with collection itself. Typically this would be 
     606        achieved by collecting the input into a StringIO. 
     607 
     608        See the implementation of `default_POST_app` for the exact details, 
     609        including how applications can accomodate both `normal` POST bodies and 
     610        `Transfer-Encoding: chunked content in the same application callable. 
     611 
     612        Applications which need to perform some long running operation must use 
     613        the ``environ['asycamore.thread_delegate]`` api. This api will set the 
     614        connection aside until the delegated operation is completed and its 
     615        result has been returned from the thread in which it was executed. See 
     616        `wsgi_a_tardy_response` for an example application which makes use of 
     617        this. 
     618 
     619        """ 
     620 
     621        v = self.create_response_context(d, use_asycamore_input=True) 
    568622        if v is self.read_sentinel: 
    569623            return v 
     
    624678            delegate() 
    625679        return pending_response 
    626  
    627  
    628 def update_log_config(force_calls=False): 
    629     global loginfo, logdebug, logconn, logtraffic 
    630     if force_calls: 
    631         return 
    632     if not log.isEnabledFor(logging.INFO): 
    633         loginfo = None 
    634     if not log.isEnabledFor(logging.DEBUG): 
    635         logdebug = None 
    636680# 
  • asycamore/trunk/asycamore/wsgistreams.py

    r740 r741  
    1212 
    1313 
    14     def __init__(self, pending, sock): 
     14    def __init__(self, pending, sock, content_length=True): 
     15        assert self.content_pending 
     16        self.content_length = content_length 
    1517        self.pending = pending 
    1618        self.rfile = sock.makefile('r')