Merge branch 'dstufft-custom-append-slash-redirect'
| | |
| | | explicitly different from ``request.response``. This does not change the |
| | | API of a renderer. See https://github.com/Pylons/pyramid/pull/1563 |
| | | |
| | | - ``Configurator().add_notfound_view()`` will now accept anything that |
| | | implements the ``IResponse`` interface and will use that as the response |
| | | class instead of the default ``HTTPFound``. |
| | | |
| | | Bug Fixes |
| | | --------- |
| | | |
| | |
| | | - Geoffrey T. Dairiki, 2015/02/06 |
| | | |
| | | - David Glick, 2015/02/12 |
| | | |
| | | - Donald Stufft, 2015/03/15 |
| | |
| | | application, this view will be invoked if the value of ``PATH_INFO`` does not |
| | | already end in a slash, and if the value of ``PATH_INFO`` *plus* a slash |
| | | matches any route's pattern. In this case it does an HTTP redirect to the |
| | | slash-appended ``PATH_INFO``. |
| | | slash-appended ``PATH_INFO``. In addition you may pass anything that implements |
| | | :class:`pyramid.interfaces.IResponse` which will then be used in place of the |
| | | default class (:class:`pyramid.httpexceptions.HTTPFound`). |
| | | |
| | | Let's use an example. If the following routes are configured in your |
| | | application: |
| | |
| | | Pyramid will return the result of the view callable provided as |
| | | ``view``, as normal. |
| | | |
| | | If the argument provided as ``append_slash`` is not a boolean but |
| | | instead implements :class:`~pyramid.interfaces.IResponse`, the |
| | | append_slash logic will behave as if ``append_slash=True`` was passed, |
| | | but the provided class will be used as the response class instead of |
| | | the default :class:`~pyramid.httpexceptions.HTTPFound` response class |
| | | when a redirect is performed. For example: |
| | | |
| | | .. code-block:: python |
| | | |
| | | from pyramid.httpexceptions import HTTPMovedPermanently |
| | | config.add_notfound_view(append_slash=HTTPMovedPermanently) |
| | | |
| | | The above means that a redirect to a slash-appended route will be |
| | | attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound` |
| | | being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will |
| | | be used` for the redirect response if a slash-appended route is found. |
| | | |
| | | .. versionchanged:: 1.6 |
| | | .. versionadded:: 1.3 |
| | | """ |
| | | for arg in ('name', 'permission', 'context', 'for_', 'http_cache'): |
| | |
| | | settings.update(predicates) |
| | | if append_slash: |
| | | view = self._derive_view(view, attr=attr, renderer=renderer) |
| | | view = AppendSlashNotFoundViewFactory(view) |
| | | if IResponse.implementedBy(append_slash): |
| | | view = AppendSlashNotFoundViewFactory( |
| | | view, redirect_class=append_slash, |
| | | ) |
| | | else: |
| | | view = AppendSlashNotFoundViewFactory(view) |
| | | settings['view'] = view |
| | | else: |
| | | settings['attr'] = attr |
| | |
| | | from pyramid.renderers import null_renderer |
| | | from zope.interface import implementedBy |
| | | from pyramid.interfaces import IRequest |
| | | from pyramid.httpexceptions import HTTPNotFound |
| | | from pyramid.httpexceptions import HTTPFound, HTTPNotFound |
| | | config = self._makeOne(autocommit=True) |
| | | config.add_route('foo', '/foo/') |
| | | def view(request): return Response('OK') |
| | |
| | | ctx_iface=implementedBy(HTTPNotFound), |
| | | request_iface=IRequest) |
| | | result = view(None, request) |
| | | self.assertTrue(isinstance(result, HTTPFound)) |
| | | self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2') |
| | | |
| | | def test_add_notfound_view_append_slash_custom_response(self): |
| | | from pyramid.response import Response |
| | | from pyramid.renderers import null_renderer |
| | | from zope.interface import implementedBy |
| | | from pyramid.interfaces import IRequest |
| | | from pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound |
| | | config = self._makeOne(autocommit=True) |
| | | config.add_route('foo', '/foo/') |
| | | def view(request): return Response('OK') |
| | | config.add_notfound_view( |
| | | view, renderer=null_renderer,append_slash=HTTPMovedPermanently |
| | | ) |
| | | request = self._makeRequest(config) |
| | | request.environ['PATH_INFO'] = '/foo' |
| | | request.query_string = 'a=1&b=2' |
| | | request.path = '/scriptname/foo' |
| | | view = self._getViewCallable(config, |
| | | ctx_iface=implementedBy(HTTPNotFound), |
| | | request_iface=IRequest) |
| | | result = view(None, request) |
| | | self.assertTrue(isinstance(result, HTTPMovedPermanently)) |
| | | self.assertEqual(result.location, '/scriptname/foo/?a=1&b=2') |
| | | |
| | | def test_add_notfound_view_with_view_defaults(self): |
| | |
| | | .. deprecated:: 1.3 |
| | | |
| | | """ |
| | | def __init__(self, notfound_view=None): |
| | | def __init__(self, notfound_view=None, redirect_class=HTTPFound): |
| | | if notfound_view is None: |
| | | notfound_view = default_exceptionresponse_view |
| | | self.notfound_view = notfound_view |
| | | self.redirect_class = redirect_class |
| | | |
| | | def __call__(self, context, request): |
| | | path = decode_path_info(request.environ['PATH_INFO'] or '/') |
| | |
| | | qs = request.query_string |
| | | if qs: |
| | | qs = '?' + qs |
| | | return HTTPFound(location=request.path+'/'+qs) |
| | | return self.redirect_class(location=request.path+'/'+qs) |
| | | return self.notfound_view(context, request) |
| | | |
| | | append_slash_notfound_view = AppendSlashNotFoundViewFactory() |
| | |
| | | redirect to the URL implied by the route; if it does not, Pyramid will |
| | | return the result of the view callable provided as ``view``, as normal. |
| | | |
| | | If the argument provided as ``append_slash`` is not a boolean but |
| | | instead implements :class:`~pyramid.interfaces.IResponse`, the |
| | | append_slash logic will behave as if ``append_slash=True`` was passed, |
| | | but the provided class will be used as the response class instead of |
| | | the default :class:`~pyramid.httpexceptions.HTTPFound` response class |
| | | when a redirect is performed. For example: |
| | | |
| | | .. code-block:: python |
| | | |
| | | from pyramid.httpexceptions import ( |
| | | HTTPMovedPermanently, |
| | | HTTPNotFound |
| | | ) |
| | | |
| | | @notfound_view_config(append_slash=HTTPMovedPermanently) |
| | | def aview(request): |
| | | return HTTPNotFound('not found') |
| | | |
| | | The above means that a redirect to a slash-appended route will be |
| | | attempted, but instead of :class:`~pyramid.httpexceptions.HTTPFound` |
| | | being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will |
| | | be used` for the redirect response if a slash-appended route is found. |
| | | |
| | | .. versionchanged:: 1.6 |
| | | |
| | | See :ref:`changing_the_notfound_view` for detailed usage information. |
| | | |
| | | """ |