def select_renderer(self, request, renderers, format_suffix=None):
        """
        Given a request and a list of renderers, return a two-tuple of:
        (renderer, media type).
        """
        accepts = self.get_accept_list(request)

        # Check the acceptable media types against each renderer,
        # attempting more specific media types first
        # NB. The inner loop here isn't as bad as it first looks :)
        #     Worst case is we're looping over len(accept_list) * len(self.renderers)
        for media_type_set in order_by_precedence(accepts):
            for renderer in renderers:
                for media_type in media_type_set:
                    if media_type_matches(renderer.media_type, media_type):
                        # Return the most specific media type as accepted.
                        media_type_wrapper = _MediaType(media_type)
                        if (_MediaType(renderer.media_type).precedence >
                                media_type_wrapper.precedence):
                            # Eg client requests '*/*'
                            # Accepted media type is 'application/json'
                            full_media_type = ';'.join(
                                (renderer.media_type, ) +
                                tuple('{0}={1}'.format(
                                    key, value.decode(HTTP_HEADER_ENCODING))
                                      for key, value in
                                      media_type_wrapper.params.items()))
                            return renderer, full_media_type
                        else:
                            # Eg client requests 'application/json; indent=8'
                            # Accepted media type is 'application/json; indent=8'
                            return renderer, media_type

        raise exceptions.NotAcceptable(available_renderers=renderers)
def media_type_matches(first, other):
    """Return true if this MediaType satisfies the given MediaType."""
    first = _MediaType(first)
    other = _MediaType(other)
    for key in first.params.keys():
        if key != 'profile' and other.params.get(key, None) != first.params.get(key, None):
            return False
    
    # handle specific profile parameter
    try:
        if not profile_matches(first.params.get('profile', None),
                               other.params.get('profile', None)):
            return False
    except ValueError:
        raise NotAcceptable("Invalid profile requested." )

    if (first.sub_type != '*' and other.sub_type != '*'  and
        other.sub_type != first.sub_type):
        return False

    if (first.main_type != '*' and other.main_type != '*' and
        other.main_type != first.main_type):
        return False

    return True
Exemple #3
0
    def select_renderer(self, request, renderers, format_suffix=None):
        """
        Given a request and a list of renderers, return a two-tuple of:
        (renderer, media type).
        """
        # Allow URL style format override.  eg. "?format=json
        format_query_param = self.settings.URL_FORMAT_OVERRIDE
        format = format_suffix or request.QUERY_PARAMS.get(format_query_param)

        if format:
            renderers = self.filter_renderers(renderers, format)
        accepts = self.get_accept_list(request)

        # Check the acceptable media types against each renderer,
        # attempting more specific media types first
        # NB. The inner loop here isn't as bad as it first looks :)
        #     Worst case is we're looping over len(accept_list) * len(self.renderers)
        for media_type_set in order_by_precedence(accepts):
            for renderer in renderers:
                for media_type in media_type_set:
                    if media_type_matches(renderer.media_type, media_type):
                        # Return the most specific media type as accepted.
                        if (_MediaType(renderer.media_type).precedence >
                                _MediaType(media_type).precedence):
                            # Eg client requests '*/*'
                            # Accepted media type is 'application/json'
                            return renderer, renderer.media_type
                        else:
                            # Eg client requests 'application/json; indent=8'
                            # Accepted media type is 'application/json; indent=8'
                            return renderer, media_type

        raise exceptions.NotAcceptable(available_renderers=renderers)
    def select_renderer(self, request, renderers, format_suffix=None):
        """
        Given a request and a list of renderers, return a two-tuple of:
        (renderer, media type).
        """
        # Allow URL style format override.  eg. "?format=json
        format_query_param = self.settings.URL_FORMAT_OVERRIDE
        format = format_suffix or request.query_params.get(format_query_param)

        if format:
            renderers = self.filter_renderers(renderers, format)

        accepts = self.get_accept_list(request)

        # Check the acceptable media types against each renderer,
        # attempting more specific media types first
        # NB. The inner loop here isn't as bad as it first looks :)
        #     Worst case is we're looping over len(accept_list) * len(self.renderers)
        for media_type_set in order_by_precedence(accepts):
            for renderer in renderers:
                for media_type in media_type_set:
                    if media_type_matches(renderer.media_type, media_type):
                        # Return the most specific media type as accepted.
                        if _MediaType(renderer.media_type).precedence > _MediaType(media_type).precedence:
                            # Eg client requests '*/*'
                            # Accepted media type is 'application/json'
                            return renderer, renderer.media_type
                        else:
                            # Eg client requests 'application/json; indent=8'
                            # Accepted media type is 'application/json; indent=8'
                            return renderer, media_type

        raise exceptions.NotAcceptable(available_renderers=renderers)
Exemple #5
0
    def determine_version(self, request, *args, **kwargs):
        """Use either Accept header or query parameter for versioning."""

        # Patterned after rest_framework.versioning.AcceptHeaderVersioning
        media_type = _MediaType(request.accepted_media_type)
        header_version = media_type.params.get(self.header_version_param, None)
        if header_version is not None:
            header_version = unicode_http_header(header_version)

        # Patterned after rest_framework.versioning.QueryParameterVersioning
        query_version = request.query_params.get(self.query_version_param,
                                                 None)

        if header_version is not None and query_version is not None and header_version != query_version:
            raise APIVersionMismatch()
        if header_version is not None and not self.is_allowed_version(
                header_version):
            # Behave like AcceptHeaderVersioning
            raise exceptions.NotAcceptable(self.invalid_version_in_header)
        if query_version is not None and not self.is_allowed_version(
                query_version):
            # Behave like QueryParameterVersioning
            raise exceptions.NotFound(self.invalid_version_in_query)
        version = header_version or query_version or self.default_version
        # self.default_version is always allowed, no need to re-check is_allowed_version here
        return version
Exemple #6
0
 def determine_version(self, request, *args, **kwargs):
     media_type = _MediaType(request.accepted_media_type)
     version = media_type.params.get(self.version_param, self.default_version)
     version = unicode_http_header(version)
     if not self.is_allowed_version(version):
         raise exceptions.NotAcceptable(self.invalid_version_message)
     return version
    def determine_version(self, request, *args, **kwargs):
        media_type = _MediaType(request.META.get('HTTP_ACCEPT'))
        version = media_type.params.get(self.version_param, 0)
        version = unicode_http_header(version)

        if not version and request.path.startswith('/schema'):
            version = request.GET.get('version', self.allowed_versions[-1])

        if version not in self.allowed_versions:
            raise exceptions.NotAcceptable({
                'detail': "Invalid version in 'Accept' header.",
                'allowed_versions': [
                    int(v) for v in self.allowed_versions
                ],
                'valid_content_types': [
                    media_type_format_json,
                    media_type_format_xml,
                    media_type_format_yaml,
                ],
                'example_header': (
                    f'Accept: {media_type_format_json}; '
                    f'version={self.allowed_versions[-1]}'
                )
            })
        request.version = version
        return version
Exemple #8
0
def modify_for_versioning(patterns, method, path, view, requested_version):
    assert view.versioning_class and view.request
    assert requested_version

    view.request.version = requested_version

    if issubclass(view.versioning_class, versioning.URLPathVersioning):
        version_param = view.versioning_class.version_param
        # substitute version variable to emulate request
        path = uritemplate.partial(path, var_dict={version_param: requested_version})
        if isinstance(path, URITemplate):
            path = path.uri
        # emulate router behaviour by injecting substituted variable into view
        view.kwargs[version_param] = requested_version
    elif issubclass(view.versioning_class, versioning.NamespaceVersioning):
        try:
            view.request.resolver_match = get_resolver(
                urlconf=tuple(detype_pattern(p) for p in patterns)
            ).resolve(path)
        except Resolver404:
            error(f"namespace versioning path resolution failed for {path}. path will be ignored.")
    elif issubclass(view.versioning_class, versioning.AcceptHeaderVersioning):
        # Append the version into request accepted_media_type.
        # e.g "application/json; version=1.0"
        # To allow the AcceptHeaderVersioning negotiator going through.
        if not hasattr(view.request, 'accepted_renderer'):
            # Probably a mock request, content negotation was not performed, so, we do it now.
            negotiated = view.perform_content_negotiation(view.request)
            view.request.accepted_renderer, view.request.accepted_media_type = negotiated
        media_type = _MediaType(view.request.accepted_media_type)
        view.request.accepted_media_type = (
            f'{media_type.full_type}; {view.versioning_class.version_param}={requested_version}'
        )

    return path
Exemple #9
0
 def test_mediatype_string_representation(self):
     mediatype = _MediaType('test/*; foo=bar')
     params_str = ''
     for key, val in mediatype.params.items():
         params_str += '; %s=%s' % (key, val)
     expected = 'test/*' + params_str
     assert str(mediatype) == expected
Exemple #10
0
    def determine_version(self, request, *args, **kwargs):
        media_type = _MediaType(request.accepted_media_type)

        version = media_type.params.get(self.version_param, None)
        if version is None:
            raise exceptions.NotAcceptable('A version is required.')

        return super(AcceptHeaderVersioningRequired,
                     self).determine_version(request, *args, **kwargs)
Exemple #11
0
 def get_header_version(self, request):
     invalid_version_message = 'Invalid version in "Accept" header.'
     media_type = _MediaType(request.accepted_media_type)
     version = media_type.params.get(self.version_param)
     if not version:
         return None
     version = unicode_http_header(version)
     if not self.is_allowed_version(version):
         raise drf_exceptions.NotAcceptable(invalid_version_message)
     return version
    def select_renderer(self, request, renderers, format_suffix=None):
        """
        Given a request and a list of renderers, return a two-tuple of:
        (renderer, media type).
        """

        # Allow URL style format override.  eg. "?format=json
        format_query_param = self.settings.URL_FORMAT_OVERRIDE
        format = format_suffix or request.query_params.get(format_query_param)

        if format:
            renderers = self.filter_renderers(renderers, format)

        accepts = self.get_accept_list(request)

        # Check the acceptable media types against each renderer,
        # attempting more specific media types first
        # NB. The inner loop here isn't as bad as it first looks :)
        #     Worst case is we're looping over len(accept_list) * len(self.renderers)
        for media_type_set in order_by_precedence(accepts):
            for renderer in renderers:
                for media_type in media_type_set:
                    if media_type_matches(renderer.media_type, media_type):
                        # Return the most specific media type as accepted.
                        media_type_wrapper = _MediaType(media_type)
                        if (
                            _MediaType(renderer.media_type).precedence >
                            media_type_wrapper.precedence
                        ):
                            # Eg client requests '*/*'
                            # Accepted media type is 'application/json'
                            full_media_type = ';'.join(
                                (renderer.media_type,) +
                                tuple('{0}={1}'.format(
                                    key, value.decode(HTTP_HEADER_ENCODING))
                                    for key, value in media_type_wrapper.params.items()))
                            return renderer, full_media_type
                        else:
                            # Eg client requests 'application/json; indent=8'
                            # Accepted media type is 'application/json; indent=8'
                            return renderer, media_type

        return (renderers[0], renderers[0].media_type)
Exemple #13
0
 def get_header_version(self, request):
     invalid_version_message = 'Invalid version in "Accept" header.'
     media_type = _MediaType(request.accepted_media_type)
     version = media_type.params.get(self.version_param)
     if not version:
         return None
     version = unicode_http_header(version)
     if not self.is_allowed_version(version):
         raise drf_exceptions.NotAcceptable(invalid_version_message)
     return version
Exemple #14
0
 def test_mediatype_match_is_false_if_keys_not_match(self):
     mediatype = _MediaType(';test_param=foo')
     another_mediatype = _MediaType(';test_param=bar')
     assert mediatype.match(another_mediatype) is False
Exemple #15
0
 def test_mediatype_string_representation(self):
     mediatype = _MediaType('test/*; foo=bar')
     assert str(mediatype) == 'test/*; foo=bar'
Exemple #16
0
 def jsonapi_params(media_type_str: str) -> bool:
     media_type = _MediaType(media_type_str)
     # We don't use _MediaType.match() because we want an *exact* match, without matching */*
     return (
         media_type.full_type == "application/vnd.api+json" and media_type.params
     )
Exemple #17
0
 def test_match_is_false_if_main_types_not_match(self):
     mediatype = _MediaType('test_1')
     anoter_mediatype = _MediaType('test_2')
     assert mediatype.match(anoter_mediatype) is False
Exemple #18
0
 def test_mediatype_precedence_with_wildcard_subtype(self):
     mediatype = _MediaType('test/*')
     assert mediatype.precedence == 1
def determine_version(request):
    media_type = _MediaType(request.META.get("HTTP_ACCEPT"))
    version = media_type.params.get("version")
    version = unicode_http_header(version)
    return version or None