summaryrefslogtreecommitdiff
path: root/docs/filewrapper.rst
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2012-01-16 03:40:51 -0500
committerChris McDonough <chrism@plope.com>2012-01-16 03:40:51 -0500
commit4b6e73772c8ddbd8effc710c421e108648cac1e5 (patch)
tree685eb64803a1e9bb9feaafc2450575b1e421fe64 /docs/filewrapper.rst
parente95e78158aa6d533044a3a80236a5db6fc70cdf1 (diff)
downloadwaitress-4b6e73772c8ddbd8effc710c421e108648cac1e5.tar.gz
Support the WSGI ``wsgi.file_wrapper`` protocol as per
http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling.
Diffstat (limited to 'docs/filewrapper.rst')
-rw-r--r--docs/filewrapper.rst52
1 files changed, 52 insertions, 0 deletions
diff --git a/docs/filewrapper.rst b/docs/filewrapper.rst
new file mode 100644
index 0000000..fe0037f
--- /dev/null
+++ b/docs/filewrapper.rst
@@ -0,0 +1,52 @@
+Support for ``wsgi.file_wrapper``
+---------------------------------
+
+Waitress supports the `WSGI file_wrapper protocol
+<http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling>`_
+. Here's a usage example::
+
+ import os
+
+ here = os.path.dirname(os.path.abspath(__file__))
+
+ def myapp(environ, start_response):
+ f = open(os.path.join(here, 'myphoto.jpg'), 'rb')
+ headers = [('Content-Type', 'image/jpeg')]
+ start_response(
+ '200 OK',
+ headers
+ )
+ return environ['wsgi.file_wrapper'](f, 32768)
+
+The file wrapper constructor is accessed via
+``environ['wsgi.file_wrapper']``. The signature of the file wrapper
+constructor is ``(filelike_object, block_size)``. Both arguments must be
+passed as positional (not keyword) arguments. The result of creating a file
+wrapper should be **returned** as the ``app_iter`` from a WSGI application.
+
+The object passed as ``filelike_object`` to the wrapper must be a file-like
+object which supports *at least* the ``read()`` method, and the ``read()``
+method must support an optional size hint argument and the ``read()`` method
+*must* return **bytes** objects (never unicode). It *should* support the
+``seek()`` and ``tell()`` methods. If it does not, normal iteration over the
+filelike object using the provided block_size is used (and copying is done,
+negating any benefit of the file wrapper). It *should* support a ``close()``
+method.
+
+The specified ``block_size`` argument to the file wrapper constructor will be
+used only when the ``filelike_object`` doesn't support ``seek`` and/or
+``tell`` methods. Waitress needs to use normal iteration to serve the file
+in this degenerate case (as per the WSGI pec), and this block size will be
+used as the iteration chunk size. The ``block_size`` argument is optional;
+if it is not passed, a default value``32768`` is used.
+
+Waitress will set a ``Content-Length`` header on the behalf of an application
+when a file wrapper with a sufficiently filelike object is used if the
+application hasn't already set one.
+
+The machinery which handles a file wrapper currently doesn't do anything
+particularly special using fancy system calls (it doesn't use ``sendfile``
+for example); using it currently just prevents the system from needing to
+copy data to a temporary buffer in order to send it to the client. No
+copying of data is done when a WSGI app returns a file wrapper that wraps a
+sufficiently filelike object. It may do something fancier in the future.