diff options
author | Gordon Chung <gord@live.ca> | 2014-06-24 16:49:39 -0400 |
---|---|---|
committer | Gordon Chung <gord@live.ca> | 2014-06-24 16:49:39 -0400 |
commit | 5abab9ed0878f175f3396b33c76d9e9d94f748a6 (patch) | |
tree | 861addb97c360d5d492fccc6ba81d56946261b4c /oslo | |
parent | 3d3da3e7a3d904dbd24a7bf56eced31ca81dc054 (diff) | |
download | oslo-middleware-5abab9ed0878f175f3396b33c76d9e9d94f748a6.tar.gz |
exported from oslo-incubator by graduate.sh
Diffstat (limited to 'oslo')
-rw-r--r-- | oslo/__init__.py | 15 | ||||
-rw-r--r-- | oslo/middleware/__init__.py | 0 | ||||
-rw-r--r-- | oslo/middleware/base.py | 56 | ||||
-rw-r--r-- | oslo/middleware/catch_errors.py | 43 | ||||
-rw-r--r-- | oslo/middleware/correlation_id.py | 28 | ||||
-rw-r--r-- | oslo/middleware/debug.py | 60 | ||||
-rw-r--r-- | oslo/middleware/request_id.py | 41 | ||||
-rw-r--r-- | oslo/middleware/sizelimit.py | 82 |
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 |