What is the most elegant way to convert DRF request requests in Django?

Consider the following thread:

public client ----> DRF API on Service A ------> DRF API on Service B

Some of the DRF APIs for service A simply proxy service B, so in a specific API on service A it looks like this:

class SomeServiceAPI(APIView):
    def get(request):
        resp = requests.get('http://service-b.com/api/...')
        return Response(resp.json())

So far this is working in normal condition, but it has several problems:

  • It does not proxy the actual status code from service b.
  • Unnecessary json serialization round in Response ()
  • If service b returns a non-json error, the service does not return the actual error from service b.

The question is, is there a better way to do this? I looked at the Django Rest Framework Proxy project , but I'm not quite sure if it really suits my use.

+4
2
  • , Response:

    return Response(resp.json(), status=resp.status_code)
    
  • , , Proxying... (, / -, , , ).

:

, URL-, -, API:

DRF:

- settings.py:

REST_PROXY = {
    'HOST': 'http://service-b.com/api/'
}

urls.py:

url(
    r'^somewere_in_a/$', 
    ProxyView.as_view(source='somewere_in_b/'), 
    name='a_name'
) 

DRF:

, :

url(
    r'^(?P<path>.*)$', 
    ProxyView.as_view(upstream='http://service-b.com/api/somewere_in_b/'),
    name='a_name'
)

: DRF Proxy ...

+2

, , , , , DRF.

# encoding: utf-8
from __future__ import unicode_literals
from __future__ import absolute_import
from rest_framework.response import Response
from requests.models import Response as RResponse


class InCompatibleError(Exception):
    pass


class DRFResponseWrapper(Response):
    """
    Wraps the requests' response
    """
    def __init__(self, data, *args, **kwargs):
        if not isinstance(data, RResponse):
            raise InCompatibleError

        status = data.status_code
        content_type = data.headers.get('content_type')

        try:
            content = data.json()
        except:
            content = data.content

        super(DRFResponseWrapper, self).__init__(content, status=status, content_type=content_type)

:

    resp = requests.get(
        '{}://{}/api/v5/business/'.format(settings.SEARCH_HOST_SCHEMA, settings.SEARCH_HOST),
        params=request.query_params
    )
    return DRFResponseWrapper(resp)
+1

Source: https://habr.com/ru/post/1683412/


All Articles