[etwist] allow to specify max size for POST request in the configuration. We should deal with this nicely on the js form validation code.
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 15 Apr 2010 12:46:08 +0200
changeset 5270 6297d5265572
parent 5251 b675edd05c19
child 5271 94e16453a640
[etwist] allow to specify max size for POST request in the configuration. We should deal with this nicely on the js form validation code.
etwist/server.py
etwist/twconfig.py
web/formfields.py
--- a/etwist/server.py	Wed Apr 14 17:38:24 2010 +0200
+++ b/etwist/server.py	Thu Apr 15 12:46:08 2010 +0200
@@ -118,6 +118,9 @@
         self.children = {}
         self.static_directories = set(('data%s' % config.instance_md5_version(),
                                        'data', 'static', 'fckeditor'))
+        global MAX_POST_LENGTH
+        MAX_POST_LENGTH = config['max-post-length'] * 1024 * 1024
+
     def init_publisher(self):
         config = self.config
         # when we have an in-memory repository, clean unused sessions every XX
@@ -295,8 +298,29 @@
                             stream=content, code=code,
                             headers=request.headers_out)
 
-#TODO
-# # XXX max upload size in the configuration
+
+orig_gotLength = http.Request.gotLength
+@monkeypatch(http.Request)
+def gotLength(self, length):
+    orig_gotLength(self, length)
+    if length > MAX_POST_LENGTH: # length is 0 on GET
+        self.clientproto = 'HTTP/1.1' # not yet initialized
+        self.channel.persistent = 0   # force connection close on cleanup
+        body = ("<html><head><title>Processing Failed</title></head><body>"
+                "<b>request max size exceeded</b></body></html>")
+        self.setResponseCode(http.BAD_REQUEST)
+        self.setHeader('content-type',"text/html")
+        self.setHeader('content-length', str(len(body)))
+        self.write(body)
+        # see request.finish(). Done here since we get error due to not full
+        # initialized request
+        self.finished = 1
+        if not self.queued:
+            self._cleanup()
+        for d in self.notifications:
+            d.callback(None)
+        self.notifications = []
+
 
 @monkeypatch(http.Request)
 def requestReceived(self, command, path, version):
--- a/etwist/twconfig.py	Wed Apr 14 17:38:24 2010 +0200
+++ b/etwist/twconfig.py	Thu Apr 15 12:46:08 2010 +0200
@@ -51,6 +51,12 @@
 the repository rather than the user running the command',
           'group': 'main', 'inputlevel': WebConfiguration.mode == 'system'
           }),
+        ('max-post-length',
+         {'type' : 'int',
+          'default': 100,
+          'help': 'maximum length of HTTP request, in Mo. Default to 100 Mo.',
+          'group': 'main', 'inputlevel': 1,
+          }),
         ('session-time',
          {'type' : 'int',
           'default': 30*60,
--- a/web/formfields.py	Wed Apr 14 17:38:24 2010 +0200
+++ b/web/formfields.py	Thu Apr 15 12:46:08 2010 +0200
@@ -589,8 +589,9 @@
             # raise UnmodifiedField instead of returning None, since the later
             # will try to remove already attached file if any
             raise UnmodifiedField()
+        # value is a 2-uple (filename, stream)
         filename, stream = value
-        # value is a  3-uple (filename, mimetype, stream)
+        # XXX avoid in memory loading of posted files. Requires Binary handling changes...
         value = Binary(stream.read())
         if not value.getvalue(): # usually an unexistant file
             value = None