Call 'close' even when raising an exception for a missing challenger.
See http://bugs.repoze.org/issue174
| | |
| | | repoze.who Changelog |
| | | ==================== |
| | | |
| | | 2.0 (unreleased) |
| | | ---------------- |
| | | |
| | | - Further harden middleware, calling ``close()`` on the iterable even if |
| | | raising an exception for a missing challenger. |
| | | http://bugs.repoze.org/issue174 |
| | | |
| | | |
| | | 2.0b1 (2011-05-24) |
| | | ------------------ |
| | | |
| | |
| | | |
| | | if api.challenge_decider(environ, wrapper.status, wrapper.headers): |
| | | logger and logger.info('challenge required') |
| | | close = getattr(app_iter, 'close', _no_op) |
| | | |
| | | challenge_app = api.challenge(wrapper.status, wrapper.headers) |
| | | if challenge_app is not None: |
| | |
| | | list(app_iter) # unwind the original app iterator |
| | | # PEP 333 requires that we call the original iterator's |
| | | # 'close' method, if it exists, before releasing it. |
| | | close = getattr(app_iter, 'close', lambda: None) |
| | | close() |
| | | # replace the downstream app with the challenge app |
| | | app_iter = challenge_app(environ, start_response) |
| | | else: |
| | | logger and logger.info('configuration error: no challengers') |
| | | close() |
| | | raise RuntimeError('no challengers found') |
| | | else: |
| | | logger and logger.info('no challenge required') |
| | |
| | | logger and logger.info(_ENDED % path_info) |
| | | return app_iter |
| | | |
| | | def _no_op(): |
| | | pass |
| | | |
| | | def wrap_generator(result): |
| | | """\ |
| | | This function returns a generator that behaves exactly the same as the |
| | |
| | | self.failUnless(result[0].startswith('401 Unauthorized\r\n')) |
| | | self.failUnless(app._iterable._closed) |
| | | |
| | | def test_call_w_challenge_but_no_challenger_still_closes_iterable(self): |
| | | environ = self._makeEnviron() |
| | | headers = [('a', '1')] |
| | | app = DummyIterableWithCloseApp('401 Unauthorized', headers) |
| | | challengers = [] |
| | | credentials = {'login':'chris', 'password':'password'} |
| | | identifier = DummyIdentifier(credentials) |
| | | identifiers = [ ('identifier', identifier) ] |
| | | authenticator = DummyAuthenticator() |
| | | authenticators = [ ('authenticator', authenticator) ] |
| | | mdprovider = DummyMDProvider({'foo':'bar'}) |
| | | mdproviders = [ ('mdprovider', mdprovider) ] |
| | | mw = self._makeOne(app=app, challengers=challengers, |
| | | identifiers=identifiers, |
| | | authenticators=authenticators, |
| | | mdproviders=mdproviders) |
| | | start_response = DummyStartResponse() |
| | | self.assertRaises(RuntimeError, mw, environ, start_response) |
| | | self.failUnless(app._iterable._closed) |
| | | |
| | | # XXX need more call tests: |
| | | # - auth_id sorting |
| | | |