summaryrefslogtreecommitdiff
path: root/oslo
diff options
context:
space:
mode:
authorGordon Chung <gord@live.ca>2014-06-24 16:49:39 -0400
committerGordon Chung <gord@live.ca>2014-06-24 16:49:39 -0400
commit5abab9ed0878f175f3396b33c76d9e9d94f748a6 (patch)
tree861addb97c360d5d492fccc6ba81d56946261b4c /oslo
parent3d3da3e7a3d904dbd24a7bf56eced31ca81dc054 (diff)
downloadoslo-middleware-5abab9ed0878f175f3396b33c76d9e9d94f748a6.tar.gz
exported from oslo-incubator by graduate.sh
Diffstat (limited to 'oslo')
-rw-r--r--oslo/__init__.py15
-rw-r--r--oslo/middleware/__init__.py0
-rw-r--r--oslo/middleware/base.py56
-rw-r--r--oslo/middleware/catch_errors.py43
-rw-r--r--oslo/middleware/correlation_id.py28
-rw-r--r--oslo/middleware/debug.py60
-rw-r--r--oslo/middleware/request_id.py41
-rw-r--r--oslo/middleware/sizelimit.py82
8 files changed, 325 insertions, 0 deletions
diff --git a/oslo/__init__.py b/oslo/__init__.py
new file mode 100644
index 0000000..c659cac
--- /dev/null
+++ b/oslo/__init__.py
@@ -0,0 +1,15 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+__import__('pkg_resources').declare_namespace(__name__) \ No newline at end of file
diff --git a/oslo/middleware/__init__.py b/oslo/middleware/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/oslo/middleware/__init__.py
diff --git a/oslo/middleware/base.py b/oslo/middleware/base.py
new file mode 100644
index 0000000..464a1cc
--- /dev/null
+++ b/oslo/middleware/base.py
@@ -0,0 +1,56 @@
+# Copyright 2011 OpenStack Foundation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Base class(es) for WSGI Middleware."""
+
+import webob.dec
+
+
+class Middleware(object):
+ """Base WSGI middleware wrapper.
+
+ These classes require an application to be initialized that will be called
+ next. By default the middleware will simply call its wrapped app, or you
+ can override __call__ to customize its behavior.
+ """
+
+ @classmethod
+ def factory(cls, global_conf, **local_conf):
+ """Factory method for paste.deploy."""
+ return cls
+
+ def __init__(self, application):
+ self.application = application
+
+ def process_request(self, req):
+ """Called on each request.
+
+ If this returns None, the next application down the stack will be
+ executed. If it returns a response then that response will be returned
+ and execution will stop here.
+ """
+ return None
+
+ def process_response(self, response):
+ """Do whatever you'd like to the response."""
+ return response
+
+ @webob.dec.wsgify
+ def __call__(self, req):
+ response = self.process_request(req)
+ if response:
+ return response
+ response = req.get_response(self.application)
+ return self.process_response(response)
diff --git a/oslo/middleware/catch_errors.py b/oslo/middleware/catch_errors.py
new file mode 100644
index 0000000..4f0d4bf
--- /dev/null
+++ b/oslo/middleware/catch_errors.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2013 NEC Corporation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Middleware that provides high-level error handling.
+
+It catches all exceptions from subsequent applications in WSGI pipeline
+to hide internal errors from API response.
+"""
+
+import webob.dec
+import webob.exc
+
+from openstack.common.gettextutils import _LE
+from openstack.common import log as logging
+from oslo.middleware import base
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CatchErrorsMiddleware(base.Middleware):
+
+ @webob.dec.wsgify
+ def __call__(self, req):
+ try:
+ response = req.get_response(self.application)
+ except Exception:
+ LOG.exception(_LE('An error occurred during '
+ 'processing the request: %s'))
+ response = webob.exc.HTTPInternalServerError()
+ return response
diff --git a/oslo/middleware/correlation_id.py b/oslo/middleware/correlation_id.py
new file mode 100644
index 0000000..9e7ccfb
--- /dev/null
+++ b/oslo/middleware/correlation_id.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2013 Rackspace Hosting
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Middleware that attaches a correlation id to WSGI request"""
+
+import uuid
+
+from oslo.middleware import base
+
+
+class CorrelationIdMiddleware(base.Middleware):
+
+ def process_request(self, req):
+ correlation_id = (req.headers.get("X_CORRELATION_ID") or
+ str(uuid.uuid4()))
+ req.headers['X_CORRELATION_ID'] = correlation_id
diff --git a/oslo/middleware/debug.py b/oslo/middleware/debug.py
new file mode 100644
index 0000000..8244a02
--- /dev/null
+++ b/oslo/middleware/debug.py
@@ -0,0 +1,60 @@
+# Copyright 2011 OpenStack Foundation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Debug middleware"""
+
+from __future__ import print_function
+
+import sys
+
+import six
+import webob.dec
+
+from oslo.middleware import base
+
+
+class Debug(base.Middleware):
+ """Helper class that returns debug information.
+
+ Can be inserted into any WSGI application chain to get information about
+ the request and response.
+ """
+
+ @webob.dec.wsgify
+ def __call__(self, req):
+ print(("*" * 40) + " REQUEST ENVIRON")
+ for key, value in req.environ.items():
+ print(key, "=", value)
+ print()
+ resp = req.get_response(self.application)
+
+ print(("*" * 40) + " RESPONSE HEADERS")
+ for (key, value) in six.iteritems(resp.headers):
+ print(key, "=", value)
+ print()
+
+ resp.app_iter = self.print_generator(resp.app_iter)
+
+ return resp
+
+ @staticmethod
+ def print_generator(app_iter):
+ """Prints the contents of a wrapper string iterator when iterated."""
+ print(("*" * 40) + " BODY")
+ for part in app_iter:
+ sys.stdout.write(part)
+ sys.stdout.flush()
+ yield part
+ print()
diff --git a/oslo/middleware/request_id.py b/oslo/middleware/request_id.py
new file mode 100644
index 0000000..e32292c
--- /dev/null
+++ b/oslo/middleware/request_id.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2013 NEC Corporation
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Middleware that ensures request ID.
+
+It ensures to assign request ID for each API request and set it to
+request environment. The request ID is also added to API response.
+"""
+
+import webob.dec
+
+from openstack.common import context
+from oslo.middleware import base
+
+
+ENV_REQUEST_ID = 'openstack.request_id'
+HTTP_RESP_HEADER_REQUEST_ID = 'x-openstack-request-id'
+
+
+class RequestIdMiddleware(base.Middleware):
+
+ @webob.dec.wsgify
+ def __call__(self, req):
+ req_id = context.generate_request_id()
+ req.environ[ENV_REQUEST_ID] = req_id
+ response = req.get_response(self.application)
+ if HTTP_RESP_HEADER_REQUEST_ID not in response.headers:
+ response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, req_id)
+ return response
diff --git a/oslo/middleware/sizelimit.py b/oslo/middleware/sizelimit.py
new file mode 100644
index 0000000..61a242f
--- /dev/null
+++ b/oslo/middleware/sizelimit.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2012 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""
+Request Body limiting middleware.
+
+"""
+
+from oslo.config import cfg
+import webob.dec
+import webob.exc
+
+from openstack.common.gettextutils import _
+from oslo.middleware import base
+
+
+# default request size is 112k
+max_req_body_size = cfg.IntOpt('max_request_body_size',
+ deprecated_name='osapi_max_request_body_size',
+ default=114688,
+ help='The maximum body size for each '
+ ' request, in bytes.')
+
+CONF = cfg.CONF
+CONF.register_opt(max_req_body_size)
+
+
+class LimitingReader(object):
+ """Reader to limit the size of an incoming request."""
+ def __init__(self, data, limit):
+ """Initiates LimitingReader object.
+
+ :param data: Underlying data object
+ :param limit: maximum number of bytes the reader should allow
+ """
+ self.data = data
+ self.limit = limit
+ self.bytes_read = 0
+
+ def __iter__(self):
+ for chunk in self.data:
+ self.bytes_read += len(chunk)
+ if self.bytes_read > self.limit:
+ msg = _("Request is too large.")
+ raise webob.exc.HTTPRequestEntityTooLarge(explanation=msg)
+ else:
+ yield chunk
+
+ def read(self, i=None):
+ result = self.data.read(i)
+ self.bytes_read += len(result)
+ if self.bytes_read > self.limit:
+ msg = _("Request is too large.")
+ raise webob.exc.HTTPRequestEntityTooLarge(explanation=msg)
+ return result
+
+
+class RequestBodySizeLimiter(base.Middleware):
+ """Limit the size of incoming requests."""
+
+ @webob.dec.wsgify
+ def __call__(self, req):
+ if (req.content_length is not None and
+ req.content_length > CONF.max_request_body_size):
+ msg = _("Request is too large.")
+ raise webob.exc.HTTPRequestEntityTooLarge(explanation=msg)
+ if req.content_length is None and req.is_body_readable:
+ limiter = LimitingReader(req.body_file,
+ CONF.max_request_body_size)
+ req.body_file = limiter
+ return self.application