Commits

Anonymous committed 3aa9015

modified patch_request_class based on mitsuhiko's recommendations

Comments (0)

Files changed (4)

 Flask-Uploads
 
-Description goes here
+It handles uploads. There's an example application in example/ that requires
+Flask-CouchDB. If you have nose installed, just run "nosetests" to run the
+tests.
 for photos, etc. - and the application can be configured to save them all in
 different places and to generate different URLs for them.
 
+.. contents::
+   :local:
+   :backlinks: none
+
 
 Configuration
 =============
 have heavy upload traffic, you can have a faster production server like Nginx
 or Lighttpd serve the uploads.
 
-Also, if you are using Flask 0.6 or greater, the `MAX_CONTENT_LENGTH` setting
-may be useful. It will limit the max size of uploaded form data, including
-files. This functionality is not available in Flask 0.5.1.
+If you are running Flask 0.6 or greater, or the application uses
+``patch_request_class(app, None)``, then you can set `MAX_CONTENT_LENGTH` to
+limit the size of uploaded files.
 
 
 Upload Sets
 
     configure_uploads(app, (photos, media))
 
-If your app has a factory function, that is a good place to place this call.
+If your app has a factory function, that is a good place to call this
+function.
+
+By default, though, Flask doesn't put any limits on the size of the uploaded
+data. To protect your application, you can use `patch_request_class`. If you
+call it with `None` as the second parameter, it will use the
+`MAX_CONTENT_LENGTH` setting to determine how large the upload can be. ::
+
+    patch_request_class(app, None)
+
+You can also call it with a number to set an absolute limit, but that only
+exists for backwards compatibility reasons and is not recommended for
+production use. In addition, it's not necessary for Flask 0.6 or greater, so
+if your application is only intended to run on Flask 0.6, you don't need it.
 
 
 File Upload Forms
     </form>
 
 
-API
-===
-Here are the API docs. These are generated directly from the source code.
+API Documentation
+=================
+This documentation is generated directly from the source code.
 
 
 Upload Sets
 -----------------
 .. autofunction:: configure_uploads
 
+.. autofunction:: patch_request_class
+
 
 Extension Constants
 -------------------
 .. autoclass:: TestingFileStorage
 
 
-Deprecated API
---------------
-.. autofunction:: patch_request_class
+Backwards Compatibility
+=======================
+
+Version 0.1.1
+-------------
+* `patch_request_class` now changes `max_content_length` instead of
+  `max_form_memory_size`.

flaskext/uploads.py

     return url + '/'
 
 
-def patch_request_class(app, size=16 * 1024 * 1024):
+def patch_request_class(app, size=64 * 1024 * 1024):
     """
-    .. warning::
+    By default, Flask will accept uploads to an arbitrary size. While Werkzeug
+    switches uploads from memory to a temporary file when they hit 500 KiB,
+    it's still possible for someone to overload your disk space with a
+    gigantic file.
     
-       This function is deprecated as of 0.1.1. As it turns out, Werkzeug
-       will automatically switch to a temporary file if the file is larger
-       than 500 KiB, so this function is unnecessary for its intended purpose.
-       If you wish to limit upload size, Flask 0.6's `MAX_CONTENT_LENGTH`
-       configuration setting is a better choice. This function is preserved
-       for backwards compatibility.
+    This patches the app's request class's
+    `~werkzeug.BaseRequest.max_content_length` attribute so that any upload
+    larger than the given size is rejected with an HTTP error.
     
-    By default, Flask will accept uploads to an arbitrary size. Unfortunately,
-    this could lead to a security hole: someone uploads a gigantic file, and
-    crashes your server when it runs out of memory. Calling this on an
-    application will patch the app's request class so that when it hits a
-    certain size, it will automatically raise an HTTP error.
+    .. note::
+       
+       In Flask 0.6, you can do this by setting the `MAX_CONTENT_LENGTH`
+       setting, without patching the request class. To emulate this behavior,
+       you can pass `None` as the size (you must pass it explicitly). That is
+       the best way to call this function, as it won't break the Flask 0.6
+       functionality if it exists.
+    
+    .. versionchanged:: 0.1.1
     
     :param app: The app to patch the request class of.
-    :param size: The maximum size to accept, in bytes. The default is 16 MiB.
+    :param size: The maximum size to accept, in bytes. The default is 64 MiB.
+                 If it is `None`, the app's `MAX_CONTENT_LENGTH` configuration
+                 setting will be used to patch.
     """
+    if size is None:
+        if isinstance(app.request_class.__dict__['max_content_length'],
+                      property):
+            return
+        size = app.config.get('MAX_CONTENT_LENGTH')
     reqclass = app.request_class
     patched = type(reqclass.__name__, (reqclass,),
-                   {'max_form_memory_size': size})
+                   {'max_content_length': size})
     app.request_class = patched
 
 

tests/test-uploads.py

 
 
 class TestMiscellaneous(object):
-    def test_patch_request_class(self):
-        app = Flask(__name__)
-        assert app.request_class.max_form_memory_size is None
-        patch_request_class(app)
-        assert app.request_class.max_form_memory_size == 16 * 1024 * 1024
-    
     def test_tfs(self):
         tfs = TestingFileStorage(filename='foo.bar')
         assert tfs.filename == 'foo.bar'