[placement] Avoid error log on 405 response

Treat HTTPMethodNotAllowed as a WSGI application rather than exception
so that it is not treated as an uncaught exception and logged as an ERROR
in the PlacementHandler before being caught in the FaultWrapper middleware.
Bad method detection is happening outside the context of WebOb wsgify
handling (which automatically catches Webob exceptions and transforms
them into appropriate responses) so we need to do the transformation
ourself.

This will help to avoid spurious noise in the logs. See the bug report
for more detail.

Change-Id: I6de7c2bffb08f370fcfbd86070c94263ee202f93
Closes-Bug: #1708167
This commit is contained in:
Chris Dent 2017-08-02 14:19:34 +01:00
parent 2decfc77d8
commit 7a895c67b1
2 changed files with 14 additions and 6 deletions

View File

@ -158,9 +158,11 @@ def handle_405(environ, start_response):
# In the process done by Routes to save the allowed methods
# to its routing table they become unicode in py2.
headers['allow'] = str(_methods)
raise webob.exc.HTTPMethodNotAllowed(
# Use Exception class as WSGI Application. We don't want to raise here.
response = webob.exc.HTTPMethodNotAllowed(
_('The method specified is not allowed for this resource.'),
headers=headers, json_formatter=util.json_error_formatter)
return response(environ, start_response)
def make_map(declarations):

View File

@ -101,11 +101,17 @@ class MapperTest(test.NoDBTestCase):
def test_405_headers(self):
environ = _environ(path='/hello', method='POST')
error = self.assertRaises(webob.exc.HTTPMethodNotAllowed,
handler.dispatch,
environ, start_response,
self.mapper)
allow_header = error.headers['allow']
global headers, status
headers = status = None
def local_start_response(*args, **kwargs):
global headers, status
status = args[0]
headers = {header[0]: header[1] for header in args[1]}
handler.dispatch(environ, local_start_response, self.mapper)
allow_header = headers['allow']
self.assertEqual('405 Method Not Allowed', status)
self.assertEqual('GET', allow_header)
# PEP 3333 requires that headers be whatever the native str
# is in that version of Python. Never unicode.