[Zope3-dev] RFC: Make HTTP streaming of large data simpler

Philipp von Weitershausen philipp at weitershausen.de
Mon Dec 5 10:27:01 EST 2005


Hi there,

while pondering on http://www.zope.org/Collectors/Zope3-dev/480, I came
across an overcomplication of the Zope 3 publishing API:


Status quo
----------

In order to stream large data over an HTTP connection, a view method
may, instead of simply returning data, set an IResult object on the
response. This would look like this (assuming that the view's context
looks like a file handle)::

  from zope.publisher.interfaces.http import IResult

  class StreamResult(object):
      implements(IResult)

      def __init__(self, context):
          self.context = context

      headers = ()

      @property
      def body(self):
          chunk = self.context.read(CHUNKSIZE)
          while chunk:
              yield chunk
              chunk = self.context.read(CHUNKSIZE)

  class StreamView(BrowserView):

      def __call__(self):
          return StreamResult(self.context)

The publisher will call the view, obtain a result object and call
HTTPResponse.setResult() with it. This method expects a) a string, b) an
object providing IResult (like in this case) or c) an object that is
adaptable to IResult. In case of an IResult object or adapter, the
'body' attribute is supposed to be an iterable, in the above example
it's a generator which would probably be a typical iterator for this case.


Proposal
--------

This is too complicated, the indirection through an extra object seems
unnecessary, especially becuase the iterable is not the object itself
but the 'body' attribute. I'm not even sure if the whole IResult thing
is necessary at all and whether somebody actually has a usecase for it.

I would really like to be able to simply write:

  class StreamView(BrowserView):

      def __call__(self):
          chunk = self.context.read(CHUNKSIZE)
          while chunk:
              yield chunk
              chunk = self.context.read(CHUNKSIZE)

So, instead of HTTPResponse.setResult() adapting the result object to
IResult, it would call iter() on it. Unless a TypeError is thrown, we
have obtained an iterable that can we can stream the result data from.
Like now, setResult() would still accept simple strings.


Looking-for-comments-ly

Philipp



More information about the Zope3-dev mailing list