안티패턴: API 프록시에서 다중 값 HTTP 헤더에 잘못된 액세스

Apigee X 문서입니다.
Apigee Edge 문서 보기

HTTP 헤더는 클라이언트 애플리케이션과 백엔드 서비스가 각각 요청 및 응답에 대한 추가 정보를 전달할 수 있도록 하는 이름 값 쌍입니다. 다음은 몇 가지 간단한 예시입니다.

  • 승인 요청 헤더는 사용자 인증 정보를 서버로 전달합니다.
    Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
  • Content-Type 헤더는 전송 중인 요청/응답 콘텐츠의 유형을 나타냅니다.
    Content-Type: application/json

HTTP 헤더에는 헤더 필드 정의에 따라 하나 이상의 값이 있을 수 있습니다. 값이 여러 개인 헤더는 쉼표로 구분된 값을 갖습니다. 다음은 여러 값을 포함하는 헤더의 몇 가지 예시입니다.

  • Cache-Control: no-cache, no-store, must-revalidate
  • Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
  • X-Forwarded-For: 10.125.5.30, 10.125.9.125

Apigee에서는 개발자가 정책 또는 조건부 흐름에서 흐름 변수를 사용하여 헤더에 쉽게 액세스할 수 있습니다. 다음은 Apigee에서 특정 요청 또는 응답 헤더에 액세스하는 데 사용할 수 있는 변수 목록입니다.

흐름 변수:

  • message.header.header-name
  • request.header.header-name
  • response.header.header-name
  • message.header.header-name.N
  • request.header.header-name.N
  • response.header.header-name.N

자바스크립트 객체:

  • context.proxyRequest.headers.header-name
  • context.targetRequest.headers.header-name
  • context.proxyResponse.headers.header-name
  • context.targetResponse.headers.header-name

다음은 요청 헤더의 값을 읽고 변수에 저장하는 방법을 보여주는 AssignMessage 정책 샘플입니다.

<AssignMessage continueOnError="false" enabled="true" name="assign-message-default">
  <AssignVariable>
    <Name>reqUserAgent</Name>
    <Ref>request.header.User-Agent</Ref>
  </AssignVariable>
</AssignMessage>

안티패턴

첫 번째 값만 반환하는 방식으로 Apigee 정책의 HTTP 헤더 값에 액세스하는 것은 잘못된 방법으로서 특정 HTTP 헤더에 값이 2개 이상 있는 경우 문제가 발생할 수 있습니다.

다음 섹션에는 헤더 액세스의 예시가 포함되어 있습니다.

예시 1: 자바스크립트 코드를 사용하여 다중 값 Accept 헤더 읽기

Accept 헤더에는 아래와 같이 값이 여러 개 있다고 가정합니다.

Accept: text/html, application/xhtml+xml, application/xml

다음은 Accept 헤더에서 값을 읽는 자바스크립트 코드입니다.

// Read the values from Accept header
var acceptHeaderValues = context.getVariable("request.header.Accept");

위의 자바스크립트 코드는 Accept 헤더의 첫 번째 값(예: text/html)만 반환합니다.

예시 2: AssignMessage 또는 RaiseFault 정책의 다중 값 Access-Control-Allow-Headers 헤더 읽기

Access-Control-Allow-Headers 헤더에는 아래와 같이 값이 여러 개 있다고 가정합니다.

Access-Control-Allow-Headers: content-type, authorization

다음은 Access-Control-Allow-Headers 헤더를 설정하는 AssignMessage 또는 RaiseFault 정책의 코드 중 일부입니다.

<Set>
  <Headers>
    <Header name="Access-Control-Allow-Headers">{request.header.Access-Control-Request-Headers}</Header>
  </Headers>
</Set>

위 코드는 요청 헤더 Access-Control-Allow-Headers의 첫 번째 값만 사용하여 Access-Control-Allow-Headers 헤더를 설정합니다(이 예시의 경우 content-type).

영향

  1. 위의 두 예에서는 다중 값 헤더의 첫 번째 값만 반환됩니다. 나중에 API 프록시 흐름의 다른 정책이나 백엔드 서비스에서 이러한 값을 사용하여 일부 함수 또는 로직을 수행하면 예기치 않은 결과 또는 결과가 발생할 수 있습니다.
  2. 액세스한 요청 헤더 값이 대상 서버로 전달되는 경우 API 요청은 백엔드에서 잘못 처리되어 잘못된 결과를 제공할 수 있습니다.
  3. 클라이언트 애플리케이션이 Apigee 응답의 특정 헤더 값에 종속되면 잘못 처리되어 잘못된 결과를 제공할 수 있습니다.

권장사항

  1. 흐름 변수의 request.header.header_name.values.string 형식을 참조하여 특정 헤더의 모든 값을 읽습니다.

    예: RaiseFault 또는 AssignMessage에서 다중 값 헤더를 읽는 데 사용할 수 있는 샘플 프래그먼트

    <Set>
      <Headers>
        <Header name="Inbound-Headers">{request.header.Accept.values.string}</Header>
      </Headers>
    </Set>
    
  2. 각각의 고유한 값에 대한 개별 액세스를 원하는 경우 적합한 기본 제공 흐름 변수를 사용할 수 있습니다. request.header.header_name.values.count ,request.header.header_name.N ,response.header.header_name.values.count ,response.header.header_name.N.

    그런 다음 반복하여 자바스크립트 또는 자바 콜아웃 정책의 특정 헤더에서 모든 값을 가져옵니다.

    예: 다중 값 헤더를 읽기 위한 샘플 자바스크립트 코드

    for (var i = 1; i <=context.getVariable('request.header.Accept.values.count'); i++)
    {
      print(context.getVariable('request.header.Accept.' + i));
    }
    

    예를 들어 application/xml;q=0.9, */*;q=0.8은 위의 코드와 함께 2개의 값으로 표시됩니다. 첫 번째 값은 application/xml;q=0.9이고 두 번째 값은 */*;q=0.8입니다.

    세미콜론을 구분기호로 헤더 값을 분할해야 하는 경우 자바스크립트 콜아웃 내에서 string.split(";")을 사용하여 고유 값을 구분할 수 있습니다.

  3. 또는 흐름 변수 request.header.header_name.values메시지 템플릿에서 사용 가능한 substring() 함수를 사용하여 특정 헤더의 모든 값을 읽을 수 있습니다.

    예: 메시지 템플릿 내에서 substring()을 사용하여 전체 다중 값 헤더 읽기

    <Set>
      <Headers>
       <Header name="Inbound-Headers">{substring(request.header.Accept.values,1,-1)}</Header>
      </Headers>
    </Set>
    

추가 자료