Esempio n. 1
0
    def test_it_adds_one_preflight_view_per_route(self, pyramid_config):
        cors_policy = policy()
        pyramid_config.add_route("api.read_thing", "/api/thing")
        pyramid_config.add_view = mock.Mock()

        add_preflight_view(pyramid_config, "api.read_thing", cors_policy)
        add_preflight_view(pyramid_config, "api.read_thing", cors_policy)

        assert pyramid_config.add_view.call_count == 1
Esempio n. 2
0
    def test_preflight_view_uses_cors_decorator(self, pyramid_config):
        cors_policy = policy()
        pyramid_config.add_route("api.read_thing", "/api/thing")
        pyramid_config.add_view = mock.Mock()

        add_preflight_view(pyramid_config, "api.read_thing", cors_policy)

        (_, kwargs) = pyramid_config.add_view.call_args
        assert kwargs["decorator"] == cors_policy
Esempio n. 3
0
    def test_it_adds_preflight_view(self, pyramid_config):
        cors_policy = policy()
        pyramid_config.add_route("api.read_thing", "/api/thing")
        add_preflight_view(pyramid_config, "api.read_thing", cors_policy)
        app = pyramid_config.make_wsgi_app()

        headers = {
            "Origin": "https://custom-client.herokuapp.com",
            "Access-Control-Request-Method": "POST",
        }
        request = Request.blank("/api/thing", method="OPTIONS", headers=headers)
        resp = request.get_response(app)

        assert resp.status_code == 200
        assert resp.body == b""
Esempio n. 4
0
def add_api_view(
    config,
    view,
    versions,
    link_name=None,
    description=None,
    enable_preflight=True,
    **settings
):

    """
    Add a view configuration for an API view.

    This configuration takes care of some common tasks for configuring
    API views:

    * It registers the view with Pyramid using some appropriate defaults for
      API method views, e.g. JSON and CORs support. As part of this, it also
      configures views to respond to requests for different versions of
      the API, via Accept header negotiation.
    * If ``link_name`` is present, the view will be registered as one of the
      available "links" that are returned by the ``api.index`` route for its
      version(s).

    :param config:
    :type config: :class:`Pyramid.config.Configurator`
    :param view: The view callable
    :param versions: API versions this view supports. Each entry must be one of
                     the versions defined in :py:const:`h.views.api.API_VERSIONS`
    :type versions: list[string] or None
    :param str link_name: Dotted path of the metadata for this route in the output
                          of the `api.index` view
    :param str description: Description of the view to use in `api.index`
    :param bool enable_preflight: If ```True``, add support for CORS preflight
                                  requests for this view. If ``True``, a
                                  `route_name` must be specified.
    :param dict settings: Arguments to pass on to ``config.add_view``
    """

    # Get the HTTP method for use in the API links metadata
    primary_method = settings.get("request_method", "GET")
    if isinstance(primary_method, tuple):
        # If the view matches multiple methods, assume the first one is
        # preferred
        primary_method = primary_method[0]

    settings.setdefault("accept", "application/json")
    settings.setdefault("renderer", "json")
    settings.setdefault("decorator", cors_policy)

    if link_name:
        link = {
            "name": link_name,
            "method": primary_method,
            "route_name": settings.get("route_name"),
            "description": description,
        }

        registry = config.registry
        if not hasattr(registry, "api_links"):
            registry.api_links = []
        registry.api_links.append(link)

    config.add_view(view=view, **settings)

    for version in versions:
        if version not in API_VERSIONS:
            raise ValueError(
                "API Configuration Error: Unrecognized API version " + version
            )

        # config.add_view only allows one, string value for `accept`, so we
        # have to re-invoke it to add additional accept headers
        settings["accept"] = "application/vnd.hypothesis." + version + "+json"
        config.add_view(view=view, **settings)

    if enable_preflight:
        cors.add_preflight_view(config, settings["route_name"], cors_policy)
def add_api_view(
    config,
    view,
    versions,
    link_name=None,
    description=None,
    enable_preflight=True,
    **settings
):

    """
    Add a view configuration for an API view.

    This configuration takes care of some common tasks for configuring
    API views:

    * It registers the view with Pyramid using some appropriate defaults for
      API method views, e.g. JSON and CORs support. As part of this, it also
      configures views to respond to requests for different versions of
      the API, via Accept header negotiation.
    * If ``link_name`` is present, the view will be registered as one of the
      available "links" that are returned by the ``api.index`` route for its
      version(s).

    :param config:
    :type config: :class:`pyramid.config.Configurator`
    :param view: The view callable
    :param versions: API versions this view supports. Each entry must be one of
                     the versions defined in :py:const:`h.views.api.API_VERSIONS`
    :type versions: list[string] or None
    :param str link_name: Dotted path of the metadata for this route in the output
                          of the `api.index` view
    :param str description: Description of the view to use in `api.index`
    :param bool enable_preflight: If ```True``, add support for CORS preflight
                                  requests for this view. If ``True``, a
                                  `route_name` must be specified.
    :param dict settings: Arguments to pass on to ``config.add_view``
    """
    settings.setdefault("renderer", "json")
    settings.setdefault("decorator", (cors_policy, version_media_type_header))

    if link_name:
        link = links.ServiceLink(
            name=link_name,
            route_name=settings.get("route_name"),
            method=settings.get("request_method", "GET"),
            description=description,
        )

        links.register_link(link, versions, config.registry)

    if API_VERSION_DEFAULT in versions:
        # If this view claims to support the default API version, register it
        # with the default (application/json) media-type accept handler
        settings.setdefault("accept", "application/json")
        config.add_view(view=view, **settings)

    for version in versions:
        if version not in API_VERSIONS:
            raise ValueError(
                "API Configuration Error: Unrecognized API version " + version
            )

        # config.add_view only allows one, string value for `accept`, so we
        # have to re-invoke it to add additional accept headers
        settings["accept"] = media_type_for_version(version)
        config.add_view(view=view, **settings)

    if enable_preflight:
        cors.add_preflight_view(config, settings["route_name"], cors_policy)
Esempio n. 6
0
def add_api_view(
    config,
    view,
    versions,
    link_name=None,
    description=None,
    enable_preflight=True,
    **settings
):

    """
    Add a view configuration for an API view.

    This configuration takes care of some common tasks for configuring
    API views:

    * It registers the view with Pyramid using some appropriate defaults for
      API method views, e.g. JSON and CORs support. As part of this, it also
      configures views to respond to requests for different versions of
      the API, via Accept header negotiation.
    * If ``link_name`` is present, the view will be registered as one of the
      available "links" that are returned by the ``api.index`` route for its
      version(s).

    :param config:
    :type config: :class:`pyramid.config.Configurator`
    :param view: The view callable
    :param versions: API versions this view supports. Each entry must be one of
                     the versions defined in :py:const:`h.views.api.API_VERSIONS`
    :type versions: list[string] or None
    :param str link_name: Dotted path of the metadata for this route in the output
                          of the `api.index` view
    :param str description: Description of the view to use in `api.index`
    :param bool enable_preflight: If ```True``, add support for CORS preflight
                                  requests for this view. If ``True``, a
                                  `route_name` must be specified.
    :param dict settings: Arguments to pass on to ``config.add_view``
    """
    settings.setdefault("renderer", "json")
    settings.setdefault("decorator", (cors_policy, version_media_type_header))

    if link_name:
        link = links.ServiceLink(
            name=link_name,
            route_name=settings.get("route_name"),
            method=settings.get("request_method", "GET"),
            description=description,
        )

        links.register_link(link, versions, config.registry)

    if API_VERSION_DEFAULT in versions:
        # If this view claims to support the default API version, register it
        # with the default (application/json) media-type accept handler
        settings.setdefault("accept", "application/json")
        config.add_view(view=view, **settings)

    for version in versions:
        if version not in API_VERSIONS:
            raise ValueError(
                "API Configuration Error: Unrecognized API version " + version
            )

        # config.add_view only allows one, string value for `accept`, so we
        # have to re-invoke it to add additional accept headers
        settings["accept"] = media_type_for_version(version)
        config.add_view(view=view, **settings)

    if enable_preflight:
        cors.add_preflight_view(config, settings["route_name"], cors_policy)