From 121f45b82f2722c0d5e5c5a7b768270299793eeb Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 8 Aug 2018 00:31:24 -0500 Subject: fix deprecated usage of request.accept in AcceptPredicate --- docs/narr/extconfig.rst | 1 + docs/narr/viewconfig.rst | 107 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 84 insertions(+), 24 deletions(-) (limited to 'docs/narr') diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst index 61bd7a05f..a9ea93e60 100644 --- a/docs/narr/extconfig.rst +++ b/docs/narr/extconfig.rst @@ -255,6 +255,7 @@ Pre-defined Phases :const:`pyramid.config.PHASE1_CONFIG` +- :meth:`pyramid.config.Configurator.add_accept_view_option` - :meth:`pyramid.config.Configurator.add_renderer` - :meth:`pyramid.config.Configurator.add_route_predicate` - :meth:`pyramid.config.Configurator.add_subscriber_predicate` diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index c463d297e..e85338573 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -285,6 +285,17 @@ Non-Predicate Arguments are just developing stock Pyramid applications. Pay no attention to the man behind the curtain. +``exception_only`` + + When this value is ``True``, the ``context`` argument must be a subclass of + ``Exception``. This flag indicates that only an :term:`exception view` should + be created, and that this view should not match if the traversal + :term:`context` matches the ``context`` argument. If the ``context`` is a + subclass of ``Exception`` and this value is ``False`` (the default), then a + view will be registered to match the traversal :term:`context` as well. + + .. versionadded:: 1.8 + Predicate Arguments +++++++++++++++++++ @@ -317,17 +328,6 @@ configured view. If ``context`` is not supplied, the value ``None``, which matches any resource, is used. -``exception_only`` - - When this value is ``True``, the ``context`` argument must be a subclass of - ``Exception``. This flag indicates that only an :term:`exception view` should - be created, and that this view should not match if the traversal - :term:`context` matches the ``context`` argument. If the ``context`` is a - subclass of ``Exception`` and this value is ``False`` (the default), then a - view will be registered to match the traversal :term:`context` as well. - - .. versionadded:: 1.8 - ``route_name`` If ``route_name`` is supplied, the view callable will be invoked only when the named route has matched. @@ -344,6 +344,20 @@ configured view. request/context pair found via :term:`resource location` does not indicate it matched any configured route. +``accept`` + A :term:`media type` that will be matched against the ``Accept`` HTTP request header. + If this value is specified, it must be a specific media type, such as ``text/html``. + If the media type is acceptable by the ``Accept`` header of the request, or if the ``Accept`` header isn't set at all in the request, this predicate will match. + If this does not match the ``Accept`` header of the request, view matching continues. + + If ``accept`` is not specified, the ``HTTP_ACCEPT`` HTTP header is not taken into consideration when deciding whether or not to invoke the associated view callable. + + See :ref:`accept_content_negotation` for more information. + + .. versionchanged:: 1.10 + Media ranges such as ``text/*`` will now raise :class:`pyramid.exceptions.ConfigurationError`. + Previously these values had undefined behavior based on the version of WebOb being used and was never fully supported. + ``request_type`` This value should be an :term:`interface` that the :term:`request` must provide in order for this view to be found and called. @@ -424,19 +438,6 @@ configured view. taken into consideration when deciding whether or not to invoke the associated view callable. -``accept`` - The value of this argument represents a match query for one or more mimetypes - in the ``Accept`` HTTP request header. If this value is specified, it must - be in one of the following forms: a mimetype match token in the form - ``text/plain``, a wildcard mimetype match token in the form ``text/*``, or a - match-all wildcard mimetype match token in the form ``*/*``. If any of the - forms matches the ``Accept`` header of the request, this predicate will be - true. - - If ``accept`` is not specified, the ``HTTP_ACCEPT`` HTTP header is not taken - into consideration when deciding whether or not to invoke the associated view - callable. - ``header`` This value represents an HTTP header name or a header name/value pair. @@ -1028,6 +1029,64 @@ these values. .. index:: single: HTTP caching +.. _accept_content_negotation: + +Accept Header Content Negotiation +--------------------------------- + +The ``accept`` argument to :meth:`pyramid.config.Configurator.add_view` can be used to control :term:`view lookup` by dispatching to different views based on the HTTP ``Accept`` request header. +Consider the below example in which there are two views, sharing the same view callable. +Each view specifies uses the accept header to trigger the appropriate response renderer. + +.. code-block:: python + + from pyramid.view import view_config + + @view_config(accept='application/json', renderer='json') + @view_config(accept='text/html', renderer='templates/hello.jinja2') + def myview(request): + return { + 'name': request.GET.get('name', 'bob'), + } + +Wildcard Accept header +++++++++++++++++++++++ + +The appropriate view is selected here when the client specifies an unambiguous header such as ``Accept: text/*`` or ``Accept: application/json``. +However, by default, if a client specifies ``Accept: */*``, the ordering is undefined. +This can be fixed by telling :app:`Pyramid` what the preferred relative ordering is between various accept mimetypes by using :meth:`pyramid.config.Configurator.add_accept_view_option`. +For example: + +.. code-block:: python + + from pyramid.config import Configurator + + def main(global_config, **settings): + config = Configurator(settings=settings) + config.add_accept_view_option('text/html') + config.add_accept_view_option( + 'application/json', + weighs_more_than='text/html', + ) + config.scan() + return config.make_wsgi_app() + +Missing Accept header ++++++++++++++++++++++ + +The above example will not match any view if the ``Accept`` header is not specified by the client. +This can be solved by adding a fallback view without an ``accept`` predicate. +For example, below the html response will be returned in all cases unless ``application/json`` is requested specifically. + +.. code-block:: python + + @view_config(accept='application/json', renderer='json') + @view_config(renderer='templates/hello.jinja2') + def myview(request): + return { + 'name': request.GET.get('name', 'bob'), + } + .. _influencing_http_caching: Influencing HTTP Caching -- cgit v1.2.3 From ed6ddcb8c7badca425093d85e23791f942dd9a34 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 29 Aug 2018 02:38:13 -0500 Subject: update docs and changelog --- docs/narr/viewconfig.rst | 52 +++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 20 deletions(-) (limited to 'docs/narr') diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index e85338573..2060393bb 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -1035,11 +1035,12 @@ Accept Header Content Negotiation --------------------------------- The ``accept`` argument to :meth:`pyramid.config.Configurator.add_view` can be used to control :term:`view lookup` by dispatching to different views based on the HTTP ``Accept`` request header. -Consider the below example in which there are two views, sharing the same view callable. -Each view specifies uses the accept header to trigger the appropriate response renderer. +Consider the example below in which there are three defined views. +Each view uses the ``Accept`` header to trigger an appropriate response renderer. .. code-block:: python + from pyramid.httpexceptions import HTTPNotAcceptable from pyramid.view import view_config @view_config(accept='application/json', renderer='json') @@ -1049,12 +1050,20 @@ Each view specifies uses the accept header to trigger the appropriate response r 'name': request.GET.get('name', 'bob'), } -Wildcard Accept header -++++++++++++++++++++++ + @view_config() + def myview_unacceptable(request): + raise HTTPNotAcceptable The appropriate view is selected here when the client specifies an unambiguous header such as ``Accept: text/*`` or ``Accept: application/json``. -However, by default, if a client specifies ``Accept: */*``, the ordering is undefined. -This can be fixed by telling :app:`Pyramid` what the preferred relative ordering is between various accept mimetypes by using :meth:`pyramid.config.Configurator.add_accept_view_option`. +Similarly, if the client specifies a media type that no view is registered to handle, such as ``Accept: text/plain``, it will fall through to ``myview_unacceptable`` and raise ``406 Not Acceptable``. +There are a few cases in which the client may specify ambiguous constraints: + +- ``Accept: */*``. +- A missing ``Accept`` header. +- An invalid ``Accept`` header. + +In these cases the preferred view is not clearly defined (see :rfc:`7231#section-5.3.2`) and :app:`Pyramid` will select one randomly. +This can be controlled by telling :app:`Pyramid` what the preferred relative ordering is between various media types by using :meth:`pyramid.config.Configurator.add_accept_view_order`. For example: .. code-block:: python @@ -1063,29 +1072,32 @@ For example: def main(global_config, **settings): config = Configurator(settings=settings) - config.add_accept_view_option('text/html') - config.add_accept_view_option( + config.add_accept_view_order('text/html') + config.add_accept_view_order( 'application/json', weighs_more_than='text/html', ) config.scan() return config.make_wsgi_app() -Missing Accept header -+++++++++++++++++++++ +In this case, the ``application/json`` view should always be selected in cases where it is otherwise ambiguous. -The above example will not match any view if the ``Accept`` header is not specified by the client. -This can be solved by adding a fallback view without an ``accept`` predicate. -For example, below the html response will be returned in all cases unless ``application/json`` is requested specifically. +Default Accept Ordering ++++++++++++++++++++++++ -.. code-block:: python +By default, :app:`Pyramid` defines a very simple priority ordering for views that prefers human-readable responses over JSON: - @view_config(accept='application/json', renderer='json') - @view_config(renderer='templates/hello.jinja2') - def myview(request): - return { - 'name': request.GET.get('name', 'bob'), - } +- ``text/html`` +- ``application/xhtml+xml`` +- ``application/xml`` +- ``text/xml`` +- ``text/plain`` +- ``application/json`` + +API clients tend to be able to specify their desired headers with more control than web browsers, and can specify the correct ``Accept`` value, if necessary. +Therefore, the motivation for this ordering is to optimize for readability. +Media types that are not listed above are ordered randomly during :term:`view lookup` between otherwise-similar views. +The defaults can be overridden using :meth:`pyramid.config.Configurator.add_accept_view_order` as described above. .. _influencing_http_caching: -- cgit v1.2.3 From 30f79dc6f3f7b6a478004ca4e41171468095c235 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 9 Sep 2018 21:18:43 -0500 Subject: enable sorting of offers --- docs/narr/extconfig.rst | 4 ++-- docs/narr/viewconfig.rst | 30 ++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'docs/narr') diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst index a9ea93e60..4c6c8b70b 100644 --- a/docs/narr/extconfig.rst +++ b/docs/narr/extconfig.rst @@ -255,12 +255,12 @@ Pre-defined Phases :const:`pyramid.config.PHASE1_CONFIG` -- :meth:`pyramid.config.Configurator.add_accept_view_option` +- :meth:`pyramid.config.Configurator.add_accept_view_order` - :meth:`pyramid.config.Configurator.add_renderer` - :meth:`pyramid.config.Configurator.add_route_predicate` - :meth:`pyramid.config.Configurator.add_subscriber_predicate` -- :meth:`pyramid.config.Configurator.add_view_predicate` - :meth:`pyramid.config.Configurator.add_view_deriver` +- :meth:`pyramid.config.Configurator.add_view_predicate` - :meth:`pyramid.config.Configurator.override_asset` - :meth:`pyramid.config.Configurator.set_authorization_policy` - :meth:`pyramid.config.Configurator.set_default_csrf_options` diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index 2060393bb..cd49d6e94 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -1027,7 +1027,8 @@ See :ref:`environment_chapter` for more information about how, and where to set these values. .. index:: - single: HTTP caching + single: Accept + single: Accept content negotation .. _accept_content_negotation: @@ -1059,10 +1060,11 @@ Similarly, if the client specifies a media type that no view is registered to ha There are a few cases in which the client may specify ambiguous constraints: - ``Accept: */*``. +- More than one acceptable media type with the same quality. - A missing ``Accept`` header. - An invalid ``Accept`` header. -In these cases the preferred view is not clearly defined (see :rfc:`7231#section-5.3.2`) and :app:`Pyramid` will select one randomly. +In these cases the preferred view is not clearly defined (see :rfc:`7231#section-5.3.2`) and :app:`Pyramid` will select one semi-randomly. This can be controlled by telling :app:`Pyramid` what the preferred relative ordering is between various media types by using :meth:`pyramid.config.Configurator.add_accept_view_order`. For example: @@ -1082,9 +1084,30 @@ For example: In this case, the ``application/json`` view should always be selected in cases where it is otherwise ambiguous. +.. _default_accept_ordering: + Default Accept Ordering +++++++++++++++++++++++ +:app:`Pyramid` will always sort multiple views with the same ``(name, context, route_name)`` first by the specificity of the ``accept`` offer. +This means that ``text/plain`` will always be offered before ``text/*``. +Similarly ``text/plain;charset=utf8`` will always be offered before ``text/plain``. +The following order is always preserved between the following offers (more preferred to less preferred): + +- ``type/subtype;params`` +- ``type/subtype`` +- ``type/*`` +- ``*/*`` + +Within each of these levels of specificity, the ordering is ambiguous and may be controlled using :meth:`pyramid.config.Configurator.add_accept_view_order`. For example, to sort ``text/plain`` higher than ``text/html`` and to prefer a ``charset=utf8`` versus a ``charset=latin-1`` within the ``text/plain`` media type: + +.. code-block:: python + + config.add_accept_view_order('text/plain', weighs_more_than='text/html') + config.add_accept_view_order('text/plain;charset=utf8', weighs_more_than='text/plain;charset=latin-1') + +It is an error to try and sort accept headers across levels of specificity. You can only sort a ``type/subtype`` against another ``type/subtype``, not against a ``type/*``. That ordering is a hard requirement. + By default, :app:`Pyramid` defines a very simple priority ordering for views that prefers human-readable responses over JSON: - ``text/html`` @@ -1099,6 +1122,9 @@ Therefore, the motivation for this ordering is to optimize for readability. Media types that are not listed above are ordered randomly during :term:`view lookup` between otherwise-similar views. The defaults can be overridden using :meth:`pyramid.config.Configurator.add_accept_view_order` as described above. +.. index:: + single: HTTP caching + .. _influencing_http_caching: Influencing HTTP Caching -- cgit v1.2.3 From f081ae991a9107363fceeeeccd361c2f85bdd046 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 27 Sep 2018 21:53:03 -0500 Subject: fix docs --- docs/narr/viewconfig.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'docs/narr') diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index cd49d6e94..7e6617b78 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -352,7 +352,7 @@ configured view. If ``accept`` is not specified, the ``HTTP_ACCEPT`` HTTP header is not taken into consideration when deciding whether or not to invoke the associated view callable. - See :ref:`accept_content_negotation` for more information. + See :ref:`accept_content_negotiation` for more information. .. versionchanged:: 1.10 Media ranges such as ``text/*`` will now raise :class:`pyramid.exceptions.ConfigurationError`. @@ -1028,9 +1028,9 @@ these values. .. index:: single: Accept - single: Accept content negotation + single: Accept content negotiation -.. _accept_content_negotation: +.. _accept_content_negotiation: Accept Header Content Negotiation --------------------------------- @@ -1084,6 +1084,9 @@ For example: In this case, the ``application/json`` view should always be selected in cases where it is otherwise ambiguous. +.. index:: + single: default accept ordering + .. _default_accept_ordering: Default Accept Ordering -- cgit v1.2.3 From ae79dfab339309f150e63be92c8ec0c58e13043e Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Tue, 2 Oct 2018 02:24:04 -0500 Subject: fix lints --- docs/narr/viewconfig.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr') diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index 7e6617b78..c44109661 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -1090,7 +1090,7 @@ In this case, the ``application/json`` view should always be selected in cases w .. _default_accept_ordering: Default Accept Ordering -+++++++++++++++++++++++ +~~~~~~~~~~~~~~~~~~~~~~~ :app:`Pyramid` will always sort multiple views with the same ``(name, context, route_name)`` first by the specificity of the ``accept`` offer. This means that ``text/plain`` will always be offered before ``text/*``. -- cgit v1.2.3 From 4a9f4f43684c3a754f43935b97013057340c305d Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 10 Oct 2018 00:04:43 -0500 Subject: deprecate range support --- docs/narr/viewconfig.rst | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'docs/narr') diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index c44109661..238599528 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -1093,23 +1093,17 @@ Default Accept Ordering ~~~~~~~~~~~~~~~~~~~~~~~ :app:`Pyramid` will always sort multiple views with the same ``(name, context, route_name)`` first by the specificity of the ``accept`` offer. -This means that ``text/plain`` will always be offered before ``text/*``. -Similarly ``text/plain;charset=utf8`` will always be offered before ``text/plain``. -The following order is always preserved between the following offers (more preferred to less preferred): +For any set of media type offers with the same ``type/subtype``, the offers with params will weigh more than the bare ``type/subtype`` offer. +This means that ``text/plain;charset=utf8`` will always be offered before ``text/plain``. -- ``type/subtype;params`` -- ``type/subtype`` -- ``type/*`` -- ``*/*`` - -Within each of these levels of specificity, the ordering is ambiguous and may be controlled using :meth:`pyramid.config.Configurator.add_accept_view_order`. For example, to sort ``text/plain`` higher than ``text/html`` and to prefer a ``charset=utf8`` versus a ``charset=latin-1`` within the ``text/plain`` media type: +By default, within a given ``type/subtype``, the order of offers is ambiguous. For example, ``text/plain;charset=utf8`` versus ``text/plain;charset=latin1`` are sorted in an unspecified way. Similarly, between media types the order is also unspecified other than the defaults described below. For example, ``image/jpeg`` versus ``image/png`` versus ``application/pdf``. In these cases, the ordering may be controlled using :meth:`pyramid.config.Configurator.add_accept_view_order`. For example, to sort ``text/plain`` higher than ``text/html`` and to prefer a ``charset=utf8`` versus a ``charset=latin-1`` within the ``text/plain`` media type: .. code-block:: python config.add_accept_view_order('text/plain', weighs_more_than='text/html') config.add_accept_view_order('text/plain;charset=utf8', weighs_more_than='text/plain;charset=latin-1') -It is an error to try and sort accept headers across levels of specificity. You can only sort a ``type/subtype`` against another ``type/subtype``, not against a ``type/*``. That ordering is a hard requirement. +It is an error to try and sort accept headers across levels of specificity. You can only sort a ``type/subtype`` against another ``type/subtype``, not against a ``type/subtype;params``. That ordering is a hard requirement. By default, :app:`Pyramid` defines a very simple priority ordering for views that prefers human-readable responses over JSON: -- cgit v1.2.3 From 4cc3a67060f22bb11d037bd44a24112efca6d507 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 10 Oct 2018 00:18:28 -0500 Subject: fix up the docs --- docs/narr/viewconfig.rst | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'docs/narr') diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index 238599528..4c8427d98 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -285,6 +285,23 @@ Non-Predicate Arguments are just developing stock Pyramid applications. Pay no attention to the man behind the curtain. +``accept`` + A :term:`media type` that will be matched against the ``Accept`` HTTP request header. + If this value is specified, it must be a specific media type such as ``text/html`` or ``text/html;level=1``. + If the media type is acceptable by the ``Accept`` header of the request, or if the ``Accept`` header isn't set at all in the request, this predicate will match. + If this does not match the ``Accept`` header of the request, view matching continues. + + If ``accept`` is not specified, the ``HTTP_ACCEPT`` HTTP header is not taken into consideration when deciding whether or not to invoke the associated view callable. + + The ``accept`` argument is technically not a predicate and does not support wrapping with :func:`pyramid.config.not_`. + + See :ref:`accept_content_negotiation` for more information. + + .. versionchanged:: 1.10 + + Specifying a media range is deprecated and will be removed in :app:`Pyramid` 2.0. + Use explicit media types to avoid any ambiguities in content negotiation. + ``exception_only`` When this value is ``True``, the ``context`` argument must be a subclass of @@ -344,20 +361,6 @@ configured view. request/context pair found via :term:`resource location` does not indicate it matched any configured route. -``accept`` - A :term:`media type` that will be matched against the ``Accept`` HTTP request header. - If this value is specified, it must be a specific media type, such as ``text/html``. - If the media type is acceptable by the ``Accept`` header of the request, or if the ``Accept`` header isn't set at all in the request, this predicate will match. - If this does not match the ``Accept`` header of the request, view matching continues. - - If ``accept`` is not specified, the ``HTTP_ACCEPT`` HTTP header is not taken into consideration when deciding whether or not to invoke the associated view callable. - - See :ref:`accept_content_negotiation` for more information. - - .. versionchanged:: 1.10 - Media ranges such as ``text/*`` will now raise :class:`pyramid.exceptions.ConfigurationError`. - Previously these values had undefined behavior based on the version of WebOb being used and was never fully supported. - ``request_type`` This value should be an :term:`interface` that the :term:`request` must provide in order for this view to be found and called. -- cgit v1.2.3 From 2a69c7b60069d5c6de7a49436c26dd329f310fea Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 10 Oct 2018 02:13:02 -0500 Subject: sentence-per-line --- docs/narr/viewconfig.rst | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'docs/narr') diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index 4c8427d98..f756fa161 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -1099,14 +1099,21 @@ Default Accept Ordering For any set of media type offers with the same ``type/subtype``, the offers with params will weigh more than the bare ``type/subtype`` offer. This means that ``text/plain;charset=utf8`` will always be offered before ``text/plain``. -By default, within a given ``type/subtype``, the order of offers is ambiguous. For example, ``text/plain;charset=utf8`` versus ``text/plain;charset=latin1`` are sorted in an unspecified way. Similarly, between media types the order is also unspecified other than the defaults described below. For example, ``image/jpeg`` versus ``image/png`` versus ``application/pdf``. In these cases, the ordering may be controlled using :meth:`pyramid.config.Configurator.add_accept_view_order`. For example, to sort ``text/plain`` higher than ``text/html`` and to prefer a ``charset=utf8`` versus a ``charset=latin-1`` within the ``text/plain`` media type: +By default, within a given ``type/subtype``, the order of offers is ambiguous. +For example, ``text/plain;charset=utf8`` versus ``text/plain;charset=latin1`` are sorted in an unspecified way. +Similarly, between media types the order is also unspecified other than the defaults described below. +For example, ``image/jpeg`` versus ``image/png`` versus ``application/pdf``. +In these cases, the ordering may be controlled using :meth:`pyramid.config.Configurator.add_accept_view_order`. +For example, to sort ``text/plain`` higher than ``text/html`` and to prefer a ``charset=utf8`` versus a ``charset=latin-1`` within the ``text/plain`` media type: .. code-block:: python config.add_accept_view_order('text/plain', weighs_more_than='text/html') config.add_accept_view_order('text/plain;charset=utf8', weighs_more_than='text/plain;charset=latin-1') -It is an error to try and sort accept headers across levels of specificity. You can only sort a ``type/subtype`` against another ``type/subtype``, not against a ``type/subtype;params``. That ordering is a hard requirement. +It is an error to try and sort accept headers across levels of specificity. +You can only sort a ``type/subtype`` against another ``type/subtype``, not against a ``type/subtype;params``. +That ordering is a hard requirement. By default, :app:`Pyramid` defines a very simple priority ordering for views that prefers human-readable responses over JSON: -- cgit v1.2.3 From 9a3238a7c21f2af1467be1bc0b1f84ee01c167a2 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 10 Oct 2018 19:52:13 -0500 Subject: improve the language around unspecified match ordering --- docs/narr/viewconfig.rst | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'docs/narr') diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index f756fa161..dd767e3f1 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -1039,8 +1039,7 @@ Accept Header Content Negotiation --------------------------------- The ``accept`` argument to :meth:`pyramid.config.Configurator.add_view` can be used to control :term:`view lookup` by dispatching to different views based on the HTTP ``Accept`` request header. -Consider the example below in which there are three defined views. -Each view uses the ``Accept`` header to trigger an appropriate response renderer. +Consider the example below in which there are three views configured. .. code-block:: python @@ -1058,16 +1057,19 @@ Each view uses the ``Accept`` header to trigger an appropriate response renderer def myview_unacceptable(request): raise HTTPNotAcceptable -The appropriate view is selected here when the client specifies an unambiguous header such as ``Accept: text/*`` or ``Accept: application/json``. +Each view relies on the ``Accept`` header to trigger an appropriate response renderer. +The appropriate view is selected here when the client specifies headers such as ``Accept: text/*`` or ``Accept: application/json, text/html;q=0.9`` in which only one of the views matches or it's clear based on the preferences which one should win. Similarly, if the client specifies a media type that no view is registered to handle, such as ``Accept: text/plain``, it will fall through to ``myview_unacceptable`` and raise ``406 Not Acceptable``. -There are a few cases in which the client may specify ambiguous constraints: + +There are a few cases in which the client may specify an ``Accept`` header such that it's not clear which view should win. +For example: - ``Accept: */*``. - More than one acceptable media type with the same quality. - A missing ``Accept`` header. - An invalid ``Accept`` header. -In these cases the preferred view is not clearly defined (see :rfc:`7231#section-5.3.2`) and :app:`Pyramid` will select one semi-randomly. +In these cases the preferred view is not clearly defined (see :rfc:`7231#section-5.3.2`) and :app:`Pyramid` will select one randomly. This can be controlled by telling :app:`Pyramid` what the preferred relative ordering is between various media types by using :meth:`pyramid.config.Configurator.add_accept_view_order`. For example: @@ -1085,7 +1087,7 @@ For example: config.scan() return config.make_wsgi_app() -In this case, the ``application/json`` view should always be selected in cases where it is otherwise ambiguous. +Now, the ``application/json`` view should always be preferred in cases where the client wasn't clear. .. index:: single: default accept ordering @@ -1099,8 +1101,8 @@ Default Accept Ordering For any set of media type offers with the same ``type/subtype``, the offers with params will weigh more than the bare ``type/subtype`` offer. This means that ``text/plain;charset=utf8`` will always be offered before ``text/plain``. -By default, within a given ``type/subtype``, the order of offers is ambiguous. -For example, ``text/plain;charset=utf8`` versus ``text/plain;charset=latin1`` are sorted in an unspecified way. +By default, within a given ``type/subtype``, the order of offers is unspecified. +For example, ``text/plain;charset=utf8`` versus ``text/plain;charset=latin1`` are sorted randomly. Similarly, between media types the order is also unspecified other than the defaults described below. For example, ``image/jpeg`` versus ``image/png`` versus ``application/pdf``. In these cases, the ordering may be controlled using :meth:`pyramid.config.Configurator.add_accept_view_order`. @@ -1108,6 +1110,8 @@ For example, to sort ``text/plain`` higher than ``text/html`` and to prefer a `` .. code-block:: python + config.add_accept_view_order('text/html') + config.add_accept_view_order('text/plain;charset=latin-1') config.add_accept_view_order('text/plain', weighs_more_than='text/html') config.add_accept_view_order('text/plain;charset=utf8', weighs_more_than='text/plain;charset=latin-1') -- cgit v1.2.3