DRF Content negotiation

허진수·2022년 7월 10일
0

Django

목록 보기
4/5

Content negotiation

HTTP에서 동일한 URI에서 리소스의 서로 다른 버전을 제공하기 위해 사용됨
클라이언트가 리소스를 내려받길 원하는 경우 URL을 사용하여 요청함
서버는 URL을 이용하여 리소스의 여러 변형(프레젠테이션)들중 하나를 선택
즉 이 리소스가 호출됐을 때 프레젠테이션을 선택하는 방법

결정 방법

HTTP 헤더를 이용(서버 주도 협상)
HTTP 응답 코드를 이용(에이전트 주도 협상, 리액티브 협상,  풀백 메커니즘으로써 사용)

서버 주도 협상

브라우저는 URL을 이용하여 몇개의 HTTP헤더 전송
서버는 그것을 힌트로써 컨텐츠 선택
때때로 요청된 리소스의 특정 프레젠테이션을 전송하는데 사용되기도 함
이러한 알고리즘은 서버 특유의 것임

헤더 목록

HTTP/1.1 표준 Accept, Accept-Charset, Accept-Encoding, Accept-Language

클라이언트 힌트

사용자 에이전트가 실행 중인 기기의 종류를 알려줌

단점

  • 클라이언트 힌트라는 확장이 있어도 서버는 브라우저에 대한 지식을 가지고 있지 않다
  • 즉 브라우저의 수용 능력에 대한 정보를 가지고 있지 않다
  • 사생활 침해에 대한 위협을 가지 있다(HTTP 핑거프린팅)
  • 주어진 리소스의 몇몇 프레젠테이션이 전송된다.
  • 샤드된 캐시들은 덜 효율적이다
  • 서버 구현은 더 복잡하다

Accept 헤더

에이전트가 처리하고자 하는 미디어 리소스의 MIME타입을 나열
쉽표로 구분, 풉질 인자 포함, 상대적 선호도를 나타냄
  • Accept-CH 헤더
    적합한 응답을 선택하기 위해 서버가 사용할 수 있는 설정 데이터를 나열

  • Accept-Charset 헤더
    사용자 에이전트가 어떤 종류의 캐릭터(문자) 인코딩을 이해 할 수 있는지 알려줌

  • Accept-Encoding 헤더
    수용 가능한 인코딩(압축 지원)을 정의
    값 - q인자 목록(우선순위를 가리킴)

  • Accept-Language 헤더
    사용자가 선호하는 언어를 가리킴

  • User-Agent 헤더
    요청을 전송하는 브라우저를 식별

에이전트 주도 협상

이 협상에서 애매모호한 요청과 마주할 경우, 서버는 사용 가능한 대체 리소스들에 대한 링크를 포함하는 페이지 회신
HTTP는 이러한 페이지의 형식을 명시하지 않음
자바스크립트 리다이렉션과 거의 항상 같이 사용됨
하나의 리소스를 가져오는데 하나 이상의 요청이 필요함

DRF Content negotiation

부분적으로 client-driven, child-driven

설정

REST_FRAMEWORK = {
    'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'myapp.negotiation.CustomNegotiatoin',
}

view에서 별도로 설정 가능

from myapp.negotiation import CustomNegotiation
from rest_framework.views import APIVew
from rest_framewor.response import Response

class sampleView(APIView):
  content_negotiation_class = CustomNegotiation
  
  def get(self, request, format=None):
    return Response({
      'accepted media type': request.accepted_renderer.media_type
    })

Custom negotiation


from rest_framework.negotiation import BaseContentNegotiation

class CustomNegotiatoin(BaseContentNegotiation):
  def select_parser(self, request, parsers):
    """
    파서 인스턴스중 하나를 사용가능한 파서 목록에서 반환
    혹은 파서가 들어오는 요청을 처리 할 수 없는 경우 None 반환
    """
    return parsers[0]

  def select_renderer(self, request, renderers, format_suffix):
    """
    (renderer instance, media type)의 tuple반환 혹은 NotAcceptable 예외
    """
    return (renderers[0], renderers[0].media_type)
profile
안녕하세요

0개의 댓글