Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge "Adds middleware to limit request body sizes."

  • Loading branch information...
commit e7068fd481f6cb887da3a8488435d7c911539bb2 2 parents 484f0a4 + 0fa7d12
authored March 29, 2012 openstack-gerrit committed March 29, 2012
19  etc/nova/api-paste.ini
@@ -92,17 +92,17 @@ use = call:nova.api.openstack.urlmap:urlmap_factory
92 92
 
93 93
 [composite:openstack_compute_api_v2]
94 94
 use = call:nova.api.auth:pipeline_factory
95  
-noauth = faultwrap noauth ratelimit osapi_compute_app_v2
96  
-deprecated = faultwrap auth ratelimit osapi_compute_app_v2
97  
-keystone = faultwrap authtoken keystonecontext ratelimit osapi_compute_app_v2
98  
-keystone_nolimit = faultwrap authtoken keystonecontext osapi_compute_app_v2
  95
+noauth = faultwrap sizelimit noauth ratelimit osapi_compute_app_v2
  96
+deprecated = faultwrap sizelimit auth ratelimit osapi_compute_app_v2
  97
+keystone = faultwrap sizelimit authtoken keystonecontext ratelimit osapi_compute_app_v2
  98
+keystone_nolimit = faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v2
99 99
 
100 100
 [composite:openstack_volume_api_v1]
101 101
 use = call:nova.api.auth:pipeline_factory
102  
-noauth = faultwrap noauth ratelimit osapi_volume_app_v1
103  
-deprecated = faultwrap auth ratelimit osapi_volume_app_v1
104  
-keystone = faultwrap authtoken keystonecontext ratelimit osapi_volume_app_v1
105  
-keystone_nolimit = faultwrap authtoken keystonecontext osapi_volume_app_v1
  102
+noauth = faultwrap sizelimit noauth ratelimit osapi_volume_app_v1
  103
+deprecated = faultwrap sizelimit auth ratelimit osapi_volume_app_v1
  104
+keystone = faultwrap sizelimit authtoken keystonecontext ratelimit osapi_volume_app_v1
  105
+keystone_nolimit = faultwrap sizelimit authtoken keystonecontext osapi_volume_app_v1
106 106
 
107 107
 [filter:faultwrap]
108 108
 paste.filter_factory = nova.api.openstack:FaultWrapper.factory
@@ -116,6 +116,9 @@ paste.filter_factory = nova.api.openstack.auth:NoAuthMiddleware.factory
116 116
 [filter:ratelimit]
117 117
 paste.filter_factory = nova.api.openstack.compute.limits:RateLimitingMiddleware.factory
118 118
 
  119
+[filter:sizelimit]
  120
+paste.filter_factory = nova.api.sizelimit:RequestBodySizeLimiter.factory
  121
+
119 122
 [app:osapi_compute_app_v2]
120 123
 paste.app_factory = nova.api.openstack.compute:APIRouter.factory
121 124
 
54  nova/api/sizelimit.py
... ...
@@ -0,0 +1,54 @@
  1
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
  2
+
  3
+# Copyright (c) 2012 OpenStack, LLC
  4
+#
  5
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
  6
+#    not use this file except in compliance with the License. You may obtain
  7
+#    a copy of the License at
  8
+#
  9
+#         http://www.apache.org/licenses/LICENSE-2.0
  10
+#
  11
+#    Unless required by applicable law or agreed to in writing, software
  12
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14
+#    License for the specific language governing permissions and limitations
  15
+#    under the License.
  16
+"""
  17
+Request Body limiting middleware.
  18
+
  19
+"""
  20
+
  21
+import webob.dec
  22
+import webob.exc
  23
+
  24
+from nova import context
  25
+from nova import flags
  26
+from nova import log as logging
  27
+from nova.openstack.common import cfg
  28
+from nova import wsgi
  29
+
  30
+
  31
+#default request size is 112k
  32
+max_request_body_size_opt = cfg.BoolOpt('osapi_max_request_body_size',
  33
+        default=114688,
  34
+        help='')
  35
+
  36
+FLAGS = flags.FLAGS
  37
+FLAGS.register_opt(max_request_body_size_opt)
  38
+LOG = logging.getLogger(__name__)
  39
+
  40
+
  41
+class RequestBodySizeLimiter(wsgi.Middleware):
  42
+    """Add a 'nova.context' to WSGI environ."""
  43
+
  44
+    def __init__(self, *args, **kwargs):
  45
+        super(RequestBodySizeLimiter, self).__init__(*args, **kwargs)
  46
+
  47
+    @webob.dec.wsgify(RequestClass=wsgi.Request)
  48
+    def __call__(self, req):
  49
+        if (req.content_length > FLAGS.osapi_max_request_body_size
  50
+            or len(req.body) > FLAGS.osapi_max_request_body_size):
  51
+            msg = _("Request is too large.")
  52
+            raise webob.exc.HTTPBadRequest(explanation=msg)
  53
+        else:
  54
+            return self.application
51  nova/tests/api/test_sizelimit.py
... ...
@@ -0,0 +1,51 @@
  1
+# Copyright (c) 2012 OpenStack, LLC
  2
+#
  3
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
  4
+#    not use this file except in compliance with the License. You may obtain
  5
+#    a copy of the License at
  6
+#
  7
+#         http://www.apache.org/licenses/LICENSE-2.0
  8
+#
  9
+#    Unless required by applicable law or agreed to in writing, software
  10
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12
+#    License for the specific language governing permissions and limitations
  13
+#    under the License.
  14
+
  15
+import webob
  16
+
  17
+import nova.api.sizelimit
  18
+from nova import flags
  19
+from nova import test
  20
+
  21
+FLAGS = flags.FLAGS
  22
+MAX_REQUEST_BODY_SIZE = FLAGS.osapi_max_request_body_size
  23
+
  24
+
  25
+class TestRequestBodySizeLimiter(test.TestCase):
  26
+
  27
+    def setUp(self):
  28
+        super(TestRequestBodySizeLimiter, self).setUp()
  29
+
  30
+        @webob.dec.wsgify()
  31
+        def fake_app(req):
  32
+            return webob.Response()
  33
+
  34
+        self.middleware = nova.api.sizelimit.RequestBodySizeLimiter(fake_app)
  35
+        self.request = webob.Request.blank('/', method='POST')
  36
+
  37
+    def test_content_length_acceptable(self):
  38
+        self.request.headers['Content-Length'] = MAX_REQUEST_BODY_SIZE
  39
+        self.request.body = "0" * MAX_REQUEST_BODY_SIZE
  40
+        response = self.request.get_response(self.middleware)
  41
+        self.assertEqual(response.status_int, 200)
  42
+
  43
+    def test_content_length_to_large(self):
  44
+        self.request.headers['Content-Length'] = MAX_REQUEST_BODY_SIZE + 1
  45
+        response = self.request.get_response(self.middleware)
  46
+        self.assertEqual(response.status_int, 400)
  47
+
  48
+    def test_request_to_large(self):
  49
+        self.request.body = "0" * (MAX_REQUEST_BODY_SIZE + 1)
  50
+        response = self.request.get_response(self.middleware)
  51
+        self.assertEqual(response.status_int, 400)

0 notes on commit e7068fd

Please sign in to comment.
Something went wrong with that request. Please try again.