Changeset 741
- Timestamp:
- 07/08/07 12:08:54 (2 years ago)
- Files:
-
- asycamore/trunk/asycamore/asycwsgi.py (modified) (1 diff)
- asycamore/trunk/asycamore/httpservicecontext.py (modified) (8 diffs)
- asycamore/trunk/asycamore/wsgistreams.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
asycamore/trunk/asycamore/asycwsgi.py
r738 r741 37 37 38 38 httpservice.update_log_config() 39 httpservicecontext.update_log_config()40 41 39 42 40 asycamore = __import__('asycamore.dispatch_' + opts.dispatcher) asycamore/trunk/asycamore/httpservicecontext.py
r738 r741 1 import sys, logging1 import sys, time, logging 2 2 from itertools import chain 3 3 from collections import deque 4 4 5 import asycamore.tcpsocket as tcpsocket 6 import asycamore.chunkedtransfer as chunkedtransfer 7 import asycamore.requestresponse as requestresponse 5 8 import asycamore.wsgienviron as wsgienviron 6 import asycamore.chunkedtransfer as chunkedtransfer 7 8 import asycamore.requestresponse as requestresponse 9 import asycamore.wsgistreams as wsgistreams 9 10 10 11 log = logging.getLogger(__name__) 11 loginfo = log.info12 12 logdebug = log.debug 13 13 … … 234 234 235 235 236 def create_response_context(self, d ):236 def create_response_context(self, d, use_asycamore_input=False): 237 237 238 238 if self.close_after_current is True: … … 276 276 277 277 environ['asycamore.response_headers'] = response_headers 278 environ['asycamore.input_read'] = self._input_read279 278 environ['asycamore.read_sentinel'] = self.read_sentinel 280 279 environ['asycamore.deferred_sentinel'] = self.deferred_sentinel … … 286 285 if cl > 0: 287 286 self.content_pending = cl 287 if not use_asycamore_input: 288 return [False, environ] 289 290 environ['asycamore.input_read'] = self._input_read 288 291 if read_chunked: 289 292 self.content_pending = True … … 291 294 chunker.next() 292 295 environ['asycamore.input_chunker' 293 ] = self._input_chunker(chunker, environ) 294 296 ] = self._input_chunker(chunker, environ) 295 297 return [False, environ] 296 298 … … 515 517 tstart = time.time() 516 518 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 517 523 def resultback(result): 518 524 # tit about because we lack chunked responses for now. … … 564 570 565 571 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) 568 622 if v is self.read_sentinel: 569 623 return v … … 624 678 delegate() 625 679 return pending_response 626 627 628 def update_log_config(force_calls=False):629 global loginfo, logdebug, logconn, logtraffic630 if force_calls:631 return632 if not log.isEnabledFor(logging.INFO):633 loginfo = None634 if not log.isEnabledFor(logging.DEBUG):635 logdebug = None636 680 # asycamore/trunk/asycamore/wsgistreams.py
r740 r741 12 12 13 13 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 15 17 self.pending = pending 16 18 self.rfile = sock.makefile('r')