흐름 변수가 있는 조건

이 페이지는 ApigeeApigee Hybrid에 적용됩니다.

Apigee Edge 문서 보기

조건문은 모든 프로그래밍 언어의 공통 제어 구조입니다. 프로그래밍 언어와 마찬가지로 API 프록시 구성은 흐름, 정책, 단계, RouteRule의 조건문을 지원합니다. 조건문을 정의하여 API에 대한 동적 동작을 정의합니다. 이러한 동적 동작을 사용하면 XML을 휴대기기 전용 JSON으로 변환하거나 요청 메시지의 콘텐츠 유형 또는 HTTP 동사에 따라 백엔드 URL로 라우팅하는 등의 작업을 수행할 수 있습니다.

이 주제에서는 코드를 작성하지 않고 조건을 사용하여 런타임에 API 관리 기능을 동적으로 적용하는 방법을 보여줍니다.

조건문 구성

조건변수의 조합을 사용하여 API 프록시에 조건부 동작을 구현합니다. Condition 요소를 사용하여 조건문을 만듭니다. 다음은 빈 조건입니다.

<Condition></Condition>

조건문을 만들려면 다음 구문을 사용하여 조건 연산자와 변수를 추가합니다.

<Condition>VARIABLE_NAME OPERATOR "VALUE"</Condition>

예를 들면 다음과 같습니다.

<Condition>request.verb = "GET"</Condition>

지원되는 조건부 연산자로는 =(같음), !=(같지 않음), >(초과)가 있습니다. 가독성을 위해 조건문을 equals, notequals, greaterthan 텍스트로 작성할 수도 있습니다.

URI 경로로 작업할 때 ~/ 또는 MatchesPath를 사용할 수 있습니다. JavaRegex 정규 표현식을 ~~ 연산자와 일치시킬 수도 있습니다.

조건은 백엔드 API 리소스의 조건부 흐름 만들기에 설명된 백엔드 API 리소스의 API 프록시 조건부 흐름을 정의하는 데 사용됩니다. 전체 조건문 목록은 조건 참조를 확인하세요.

변수

조건은 변수의 값을 평가하는 방식으로 작동합니다. 변수는 API 프록시에서 실행되는 HTTP 트랜잭션의 속성이거나 API 프록시 구성 자체의 속성입니다. API 프록시가 앱에서 요청을 받을 때마다 Apigee는 시스템 시간, 앱의 네트워크 정보, 메시지의 HTTP 헤더, API 프록시 구성, 정책 실행 등과 관련된 긴 변수 목록을 채웁니다. 이렇게 하면 조건문을 설정하는 데 사용할 수 있는 풍부한 컨텍스트가 생성됩니다.

변수는 항상 점 표기법을 사용합니다. 예를 들어 요청 메시지의 HTTP 헤더는 request.header.HEADER_NAME이라는 변수로 사용할 수 있습니다. 따라서 Content-type header를 평가하려면 request.header.Content-type 변수를 사용하면 됩니다. 예를 들어 request.header.Content-type = "application/json"은 요청의 콘텐츠 유형이 JSON이어야 함을 나타냅니다.

요청 메시지가 GET일 때만 정책을 시행하는 조건문을 만들어야 한다고 가정해 보겠습니다. 요청의 HTTP 동사를 평가하는 조건을 만들려면 아래 조건문을 만듭니다. 이 조건의 변수는 request.verb입니다. 변수의 값은 GET입니다. 연산자는 =입니다.

<Condition>request.verb = "GET"</Condition>

다음과 같은 문을 사용해도 됩니다.

<Condition>request.verb equals "GET"</Condition>

Apigee에서는 이러한 문을 사용하여 조건을 평가합니다. 위 예시의 경우 요청과 연결된 HTTP 동사가 GET이면 true로 평가됩니다. 요청과 연결된 HTTP 동사가 POST이면 문이 false로 평가됩니다.

동적 동작을 사용 설정하려면 Flow, Step, RouteRule에 조건을 연결하면 됩니다.

흐름에 조건을 연결하면 조건부 흐름이 생성됩니다. 조건부 흐름은 조건이 true로 평가될 때만 실행됩니다. 조건부 흐름에 원하는 만큼 정책을 연결할 수 있습니다. 조건부 흐름을 사용하면 특정 기준을 충족하는 요청 또는 응답 메시지에 대한 특수 처리 규칙을 만들 수 있습니다.

예를 들어 요청 동사가 GET일 때만 실행되는 흐름을 만들려면 다음 문을 사용합니다.

<Flows>
  <Flow name="ExecuteForGETs">
  <Condition>request.verb="GET"</Condition>
  </Flow>
</Flows>

GET 요청 및 POST 요청의 흐름을 각각 하나씩 만들려면 다음 문을 사용합니다.

<Flows>
  <Flow name="ExecuteForGETs">
    <Condition>request.verb="GET"</Condition>
  </Flow>
  <Flow name="ExecuteForPOSTs">
    <Condition>request.verb="POST"</Condition>
  </Flow>
</Flows>

아래 예시에 나온 것처럼 정책 단계 자체에 조건을 적용할 수 있습니다. 다음 조건은 요청 메시지가 POST인 경우에만 VerifyApiKey 정책이 적용되도록 합니다.

<PreFlow name="PreFlow">
    <Request>
        <Step>
            <Condition>request.verb equals "POST"</Condition>
            <Name>VerifyApiKey</Name>
        </Step>
    </Request>
</PreFlow>

이러한 조건부 흐름을 정의하면 정책을 연결하여 API 프록시가 GET 요청에 하나의 정책 집합을 적용하고 POST 요청에 다른 정책 집합을 적용하도록 할 수 있습니다.

포괄적인 참조 정보는 다음 리소스를 확인하세요.

예시 1

다음 예시는 ProxyEndpoint 응답 흐름에서 구성된 Convert-for-devices라는 단일 조건부 흐름을 보여줍니다. 조건이 적용되는 항목에 조건을 요소로 추가합니다. 이 예시에서 조건은 흐름의 구성요소입니다. 따라서 문이 true로 평가될 때마다 흐름이 실행됩니다.

<Flows>
  <Flow name="Convert-for-devices">
  <Condition>(request.header.User-Agent = "Mozilla")</Condition>
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

앱에서 수신한 요청마다 Apigee에서 표시된 모든 HTTP 헤더 값을 변수로 저장합니다. 요청에 User-Agent라는 HTTP 헤더가 포함된 경우 헤더와 헤더 값은 request.header.User-Agent라는 변수로 저장됩니다.

Apigee는 위의 ProxyEndpoint 구성을 감안해 request.header.User-Agent 변수의 값을 검사하여 조건이 true로 평가되는지 확인합니다.

조건이 true로 평가되는 경우 즉 변수 request.header.User-Agent의 값이 Mozilla와 같다면 조건부 흐름이 실행되고 ConvertToJSON이라는 XMLtoJSON 정책이 적용됩니다. 그렇지 않으면 흐름이 실행되지 않고 XML 응답이 수정되지 않고 XML 형식으로 요청 앱에 반환됩니다.

예시 2

응답 메시지를 XML에서 JSON으로 변환해야 하는 특정 예시를 사용해 보겠습니다(휴대기기 전용). 먼저 Weather API의 XML 형식 응답을 JSON으로 변환하는 정책을 만듭니다.

<XMLToJSON name="ConvertToJSON">
  <Options>
  </Options>
  <OutputVariable>response</OutputVariable>
  <Source>response</Source>
</XMLToJSON>

위의 정책 구성은 API 프록시에 응답 메시지를 받고 기본 설정을 사용하여 XML을 JSON으로 변환한 다음 결과를 새 응답 메시지에 작성하도록 지시합니다. 요청 메시지를 XML에서 JSON으로 변환하는 경우 두 값 모두 request로 설정하면 됩니다.

XML의 응답을 JSON으로 변환해야 하므로 변환을 수행하도록 조건부 응답 흐름을 구성해야 합니다. 예를 들어 클라이언트 앱으로 반환되기 전에 모든 응답을 XML에서 JSON으로 변환하려면 다음 ProxyEndpoint 응답 흐름을 구성합니다.

<Flows>
  <Flow name="Convert-for-devices">
    <Response>
      <Step><Name>ConvertToJSON</Name></Step>
    </Response>
  </Flow>
</Flows>

표준 요청을 사용하여 API를 호출하면 응답 형식이 JSON으로 지정됩니다.

하지만 요청 클라이언트가 휴대기기일 때 날씨 보고서를 JSON으로 변환하는 것이 목표입니다. 이러한 동적 동작을 사용 설정하려면 흐름에 조건문을 추가해야 합니다.

조건부 흐름 테스트

이 샘플 요청에서는 HTTP User-Agent 헤더가 Mozilla로 설정되어 조건문이 true로 평가되고 조건부 흐름 Convert-for-devices가 실행됩니다.

curl -H "User-Agent:Mozilla" http://example.com/weather/forecastrss?w=12797282

또는 Python을 사용할 수 있는 경우 읽기 쉽게 출력됩니다.

curl -H "User-Agent:Mozilla" http://example.com/weather/forecastrss?w=12797282 | python -mjson.tool

샘플 응답:

. . .

"yweather_forecast": [
   {
      "code": "11",
      "date": "12 Dec 2012",
      "day": "Wed",
      "high": "55",
      "low": "36",
      "text": "Showers"
    },
    {
      "code": "32",
      "date": "13 Dec 2012",
      "day": "Thu",
      "high": "56",
      "low": "38",
      "text": "Sunny"
    }
  ]
}

. . .

User-Agent 헤더가 없거나 Mozilla 값과 다른 값이 포함된 요청이 제출되면 XML 형식의 응답이 생성됩니다.

$ curl http://example.com/weather/forecastrss?w=12797282

수정되지 않은 XML 응답이 반환됩니다.

샘플 응답:

<yweather:forecast day="Wed" date="12 Dec 2012" low="36" high="55" text="Showers" code="11" /> <yweather:forecast day="Thu" date="13 Dec 2012" low="38" high="56" text="Sunny" code="32" />

패턴 일치

이 섹션에서는 Apigee 흐름에서 조건과 패턴 일치를 사용하는 방법을 설명합니다.

연산자

이 섹션에서는 조건문에 다음과 같은 패턴 일치 연산자를 사용하는 방법을 설명합니다.

일치

먼저 Matches 또는 ~ 조건부 연산자를 살펴보겠습니다. 이 두 연산자는 동일합니다. 영어 버전인 Matches가 더 읽기 쉬운 것으로 간주됩니다.

요약: Matches 연산자는 두 가지 가능성을 제공합니다. 문자열을 문자 그대로 일치시키거나 *로 와일드 카드 일치를 수행합니다. 예상한 것처럼 와일드 카드는 0개 이상의 문자와 일치합니다. 그럼 방법을 알아보겠습니다.

다음 XML은 단계 조건을 보여줍니다. 조건이 true로 평가될 때 SomePolicy 정책을 실행합니다. 이 예시에서는 요청의 경로 서픽스를 저장하는 Apigee의 기본 제공 변수인 proxy.pathsuffix 변수를 테스트합니다. 그러나 문자열이 포함된 모든 흐름 변수의 값을 테스트할 수 있습니다. 따라서 이 경우 수신 요청의 기본 경로가 /animals이고 요청은 /animals/cat이면 경로 서픽스는 리터럴 문자열 /cat입니다.

<PreFlow name="PreFlow">
  <Request>
    <Step>
      <Condition>(proxy.pathsuffix Matches "/cat")</Condition>
      <Name>SomePolicy</Name>
    </Step>
  </Request>
  <Response/>
</PreFlow>

질문: SomePolicy가 실행되도록 하는 프록시 경로 서픽스는 무엇인가요? 하나밖에 없습니다.

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 예. 프록시 경로 서픽스가 /cat과 정확히 일치하기 때문입니다. 서픽스가 /bat, /dog, / 또는 그 외인 경우 실행되지 않습니다.

이제 와일드 카드 문자 *를 사용하는 다음 조건문을 살펴보겠습니다.

<Condition>(proxy.pathsuffix Matches "/*at")</Condition>

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 예. 와일드 카드는 모든 문자와 일치하므로 "/cat"은 일치합니다.

API 호출:

GET http://example.com/matchtest/bat

정책이 실행되나요? 예. 와일드 카드는 모든 문자와 일치하므로 "/bat"은 일치합니다.

API 호출:

GET http://example.com/matchtest/owl

정책이 실행되나요? 아니요. 와일드 카드가 o와 일치하지만 wl 문자는 일치하지 않습니다.

이제 와일드 카드를 서픽스 끝으로 옮겨 보겠습니다.

<Condition>(proxy.pathsuffix Matches "/cat*")</Condition>

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 예. 와일드 카드가 0개 이상의 문자와 일치하기 때문입니다.

API 호출:

GET http://example.com/matchtest/bat

정책이 실행되나요? 아니요. /bat은 일치하지 않습니다.

API 호출:

GET http://example.com/matchtest/cat123

정책이 실행되나요? 예. 와일드 카드는 0개 이상의 문자와 일치하므로 123은 일치합니다.

API 호출:

GET http://example.com/matchtest/cat/bird/mouse

정책이 실행되나요? 예. 와일드 카드가 0개 이상의 문자와 일치하므로 /bird/mouse는 일치합니다. 이와 같은 표현식은 리터럴 문자 뒤의 모든 항목과 일치하므로 문제가 발생할 수 있습니다.

질문: Matches 연산자는 대소문자를 구분하나요?

예. 다음과 같은 조건이 있다고 가정해 보겠습니다.

<Condition>(proxy.pathsuffix Matches "/*At")</Condition>

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 아니요. 와일드 카드는 대소문자에 관계없이 모든 문자와 일치하지만 소문자 aA와 일치하지 않습니다.

API 호출:

GET http://example.com/matchtest/bAt

정책이 실행되나요? 예. 대소문자가 일치합니다.

질문: Matches 연산자를 사용하여 문자를 이스케이프 처리하려면 어떻게 해야 하나요?

퍼센트(%) 문자를 사용하여 예약된 문자를 이스케이프 처리합니다. 예를 들면 다음과 같습니다.

<Condition>(proxy.pathsuffix Matches "/c%*at")</Condition>

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 아니요. Matches 연산자는 리터럴 문자열 c*at을 찾습니다.

API 호출:

GET http://example.com/matchtest/c*at

질문: 정책이 실행되나요?

예. 이 경로는 약간 이상하긴 하지만 일치합니다.

JavaRegex

보다시피 Matches 연산자는 간단한 상황에서 매우 효과적입니다. 하지만 다른 연산자, JavaRegex 또는 ~~ 연산자도 사용할 수 있습니다. 이 두 연산자는 동일한 연산자지만 JavaRegex가 더 읽기 쉬운 것으로 간주됩니다. 이는 정규 표현식 패턴 일치를 허용하므로 JavaRegex라고 부릅니다. Apigee는 자바 언어의 java.util.regex package 클래스와 동일한 규칙을 따릅니다. JavaRegex 연산자가 작동하는 방식은 Matches 연산자와 매우 다르므로 두 연산자를 혼동하지 않도록 해야 합니다.

요약: JavaRegex 연산자를 사용하면 조건문에 정규 표현식 구문을 사용할 수 있습니다.

다음 코드는 단계 조건을 보여줍니다. 조건이 true로 평가되면 SomePolicy 정책을 실행합니다. 이 예시에서는 요청의 경로 서픽스를 저장하는 Apigee의 기본 제공 변수인 proxy.pathsuffix 변수를 테스트합니다. 수신 요청의 기본 경로가 /animals이고 요청은 /animals/cat이면 경로 서픽스는 리터럴 문자열 /cat입니다.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix JavaRegex "/cat")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

질문: SomePolicy가 실행되도록 하는 프록시 경로 서픽스는 무엇인가요? 이 경우 Matches 연산자와 마찬가지로 한 가지 서픽스밖에 없습니다.

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 예. 프록시 경로 서픽스가 /cat과 정확히 일치하기 때문입니다. 서픽스가 /bat 또는 /dog인 경우 실행되지 않습니다.

이제 * 수량자를 사용하여 정규 표현식을 만들어 보겠습니다. 이 수량자는 선행 문자 0개 이상과 일치합니다.

<Condition>(proxy.pathsuffix JavaRegex "/c*t")</Condition>

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 아니요. * 수량자는 0개 이상의 선행 문자(c)와 일치합니다.

API 호출:

GET http://example.com/matchtest/ccccct

정책이 실행되나요? 예. 와일드 카드가 0개 이상의 선행 문자와 일치하기 때문입니다.

다음으로, 선행 문자와 한 번 일치하거나 아예 일치하지 않는 ? 수량자를 사용하겠습니다.

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 예. ? 수량자는 선행 문자의 어커런스 0개 또는 1개(a)와 일치합니다.

API 호출:

GET http://example.com/matchtest/ct

정책이 실행되나요? 예. ? 수량자는 선행 문자 1개 또는 0개와 일치합니다. 이 경우에는 a 문자가 없으므로 조건이 true로 평가됩니다.

API 호출:

GET http://example.com/matchtest/caat

정책이 실행되나요? 아니요. ? 수량자는 선행 문자 하나(a)와 일치합니다.

다음으로 정규 표현식의 [abc] 또는 그룹화 스타일을 사용합니다. 이는 a 또는 b 또는 c 문자와 일치합니다.

<Condition>(proxy.pathsuffix JavaRegex "/[cbr]at")</Condition>

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 예. 여기서는 정규 표현식을 사용하고 있으며 [cbr] 표현식은 c, b 또는 r과 일치합니다. 다음과 같은 호출도 일치합니다.

GET http://example.com/matchtest/bat

GET http://example.com/matchtest/rat

하지만 일치 항목이 아닙니다.

GET http://example.com/matchtest/mat

질문: JavaRegex 연산자는 대소문자를 구분하나요?

예. 다음과 같은 조건이 있다고 가정해 보겠습니다.

<Condition>(proxy.pathsuffix JavaRegex "/ca?t")</Condition>

API 호출:

GET http://example.com/matchtest/cat

정책이 실행되나요? 예. 정규식은 선행 문자 0개 또는 1개(a)와 일치합니다.

API 호출:

GET http://example.com/matchtest/cAt

질문: 정책이 실행되나요?

아니요. 대문자 A는 소문자 a와 일치하지 않기 때문입니다.

MatchesPath

~/와 같이 MatchesPath 연산자도 지정할 수 있습니다. 이는 Matches(~) 및 JavaRegex(~~) 연산자와 약간 유사합니다. 하지만 MatchesPath는 완전히 다릅니다.

이 연산자는 경로를 연속된 부분으로 봅니다. 따라서 경로가 /animals/cats/wild이면 /animals, /cats, /wild 부분으로 구성된 것으로 볼 수 있습니다.

MatchesPath 연산자를 사용하면 두 개의 와일드 카드 표기법, 즉 별표(*) 한 개와 별표 두 개(**)를 사용할 수 있습니다. 단일 별표는 하나의 경로 요소와 일치합니다. 이중 별표는 하나 이상의 경로 요소와 일치합니다.

예시를 살펴보겠습니다. 이 예시에서는 요청의 경로 서픽스를 저장하는 Apigee의 기본 제공 변수인 proxy.pathsuffix 변수를 테스트합니다. 그러나 문자열이 포함된 모든 흐름 변수의 값을 테스트할 수 있습니다.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

질문: SomePolicy가 실행되도록 하는 프록시 경로 서픽스는 무엇인가요?

API 호출:

GET http://example.com/matchtest/animals

질문: 정책이 실행되나요?

아니요. 조건에 따라 /*로 지정된 /animals 다음에 다른 경로 요소가 필요하기 때문입니다.

API 호출:

GET http://example.com/matchtest/animals/

정책이 실행되나요? 예. 경로에 다른 경로 요소(/animals/ 다음 부분)가 있지만 비어 있습니다.

API 호출:

GET http://example.com/matchtest/animals/cats

정책이 실행되나요? 예. 경로에 /animals 이후에 오는 요소(/cats)가 명확하게 포함되어 있기 때문입니다.

API 호출:

GET http://example.com/matchtest/animals/cats/wild

질문: 정책이 실행되나요?

아니요. 단일 별표는 하나의 경로 요소와 일치하고 이 API에는 /animals 다음 요소가 두 개 이상 있기 때문입니다.

이제 이중 별표를 사용해보겠습니다.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

질문: SomePolicy가 실행되도록 하는 프록시 경로 서픽스는 무엇인가요?

API 호출:

GET http://example.com/matchtest/animals

정책이 실행되나요? 아니요. 조건에는 /**에 의해 지정된 다음 경로 요소가 하나 이상 필요하기 때문입니다.

API 호출:

GET http://example.com/matchtest/animals/

정책이 실행되나요?

예. 경로에 다른 경로 요소(/animals/ 다음 부분)가 있지만 비어 있습니다.

API 호출:

GET http://example.com/matchtest/animals/cats

정책이 실행되나요?

예. 경로에 /animals 다음 요소가 하나 이상 있기 때문입니다.

API 호출:

GET http://example.com/matchtest/animals/cats/wild

정책이 실행되나요?

예. 경로에 /animals 다음 요소가 2개 이상 있기 때문입니다.

별표 조합

단일(*) 및 이중(**) 별표 조합을 사용하여 경로 일치를 더욱 세분화할 수 있습니다.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix MatchesPath "/animals/*/wild/**")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

API 호출:

이러한 모든 API 호출은 일치 항목을 생성합니다.

GET http://example.com/matchtest/animals/cats/wild/

GET http://example.com/matchtest/animals/dogs/wild/austrailian



GET http://example.com/matchtest/animals/birds/wild/american/finches

API 리소스

RESTful 서비스는 API 리소스 모음입니다. API 리소스는 개발자가 API를 호출하여 액세스할 수 있는 일부 항목을 식별하는 URI 경로 프래그먼트입니다. 예를 들어 날씨 보고서와 일기 예보를 제공하는 서비스의 경우 백엔드 서비스에서 다음과 같은 2개의 API 리소스를 정의할 수 있습니다.

  • http://mygreatweatherforecast.com/reports
  • http://mygreatweatherforecast.com/forecasts

첫 번째 API 프록시 빌드에 나온 것처럼 API 프록시를 만들 때는 최소한 백엔드 서비스에 매핑되는 별칭 기본 URL을 만듭니다. 예를 들면 다음과 같습니다.

백엔드 기본 URL 신규/상응 API 프록시 URL
http://mygreatweatherforecast.com http://example.com/mygreatweatherforecast

이 시점에서 기본 URL을 사용하여 백엔드에 API를 호출할 수 있습니다. 하지만 API 프록시 URL을 사용하면 흥미로운 상황이 발생합니다.

API 프록시를 사용하면 Apigee에서 API 분석을 수집하기 시작하는 것은 물론, 프록시를 통해 백엔드의 리소스에 매핑되는 조건부 흐름을 정의할 수 있습니다. 기본적으로 GET 호출이 /reports 리소스에 수신되면 Apigee에서 무언가를 해야 합니다.

다음 이미지는 결국에는 동일한 백엔드에 액세스하는 두 URL의 동작에 어떤 차이가 있는지 보여줍니다. 하나는 프록시되지 않은 리소스 URL이고 다른 하나는 동일한 백엔드 리소스에 대한 조건부 흐름이 포함된 Apigee API 프록시입니다. 조건부 흐름에 대한 자세한 내용은 아래에서 다룰 예정입니다.

조건부 흐름이 포함된 Apigee API 프록시 URL의 경우 응답이 XML을 JSON으로 변환하고 분석을 수집합니다.

API 프록시에서 특정 백엔드 리소스에 매핑하는 방법

프록시를 만들 때 백엔드 서비스의 기본 URL에 API 프록시 URL이 매핑된 경우 앞서 말한 /reports/forecasts 리소스와 같은 특정 리소스에 조건부 흐름을 추가할 수 있습니다.

/reports 또는 /forecasts 리소스에 대한 호출이 발생하면 Apigee가 특정 작업을 수행하도록 한다고 가정해 보겠습니다. 이 시점에서 Apigee에 리소스에 대한 호출을 리슨해야 함을 알릴 뿐 무엇을 수행해야 하는지는 알리지 않습니다. 이는 조건을 사용하여 수행합니다. Apigee API 프록시에서 /reports/forecasts의 조건부 흐름을 만들 수 있습니다. 개념을 설명하기 위해 다음 API 프록시 XML은 이러한 조건의 형식을 보여줍니다.

<Flows>
    <Flow name="reports">
        <Description/>
        <Request/>
        <Response/>
        <Condition>(proxy.pathsuffix MatchesPath "/reports") and (request.verb = "GET")</Condition>
    </Flow>
    <Flow name="forecasts">
        <Description/>
        <Request/>
        <Response/>
        <Condition>(proxy.pathsuffix MatchesPath "/forecasts") and (request.verb = "GET")</Condition>
    </Flow>
</Flows>

URL에 /reports/forecasts가 포함된 GET 요청이 들어오면 Apigee에서 API 개발자가 이러한 흐름에 연결한 정책을 통해 개발자가 지시한 작업을 수행한다는 내용입니다.

조건이 충족되면 Apigee가 수행해야 할 작업을 알려주는 예는 다음과 같습니다. 다음 API 프록시 XML에서 GET 요청이 https://example.com/mygreatweatherforecast/reports로 전송되면 Apigee가 응답에 XML-to-JSON-1 정책을 실행합니다.

<Flows>
  <Flow name="reports">
    <Description/>
    <Request/>
    <Response>
      <Step>
        <Name>XML-to-JSON-1</Name>
      </Step>
    </Response>
  <Condition>(proxy.pathsuffix MatchesPath "/reports") and (request.verb = "GET")</Condition>
</Flow>

이러한 선택적 조건부 흐름 외에도 각 API 프록시에는 두 가지 기본 흐름, 즉 조건부 흐름 이전에 실행된 <PreFlow> 및 조건부 흐름 후에 실행된 <PostFlow>와 함께 제공됩니다. 이는 API 프록시에 대한 호출이 수행되는 모든 경우 정책을 실행하는 데 유용합니다. 예를 들어 백엔드 리소스가 액세스되는 여부와 상관없이 호출할 때마다 앱의 API 키를 확인하려는 경우 API 키 검증 정책을 <PreFlow>에 적용할 수 있습니다. 흐름에 대한 자세한 내용은 흐름 구성을 참조하세요.

백엔드 리소스에 대한 조건부 흐름 만들기

API 프록시에서 백엔드 리소스에 대한 조건부 흐름을 정의하는 것은 전적으로 선택사항입니다. 하지만 이러한 조건부 흐름을 통해 세밀한 관리 및 모니터링을 적용할 수 있습니다.

다음 작업을 할 수 있습니다.

  • API 모델의 시맨틱스를 반영하는 방식으로 관리 적용
  • 정책 및 스크립트 동작을 개별 리소스 경로(URI)에 적용
  • 분석 서비스의 세분화된 측정항목 수집

예를 들어 백엔드 /developers~/apps 리소스에 다양한 유형의 로직을 적용해야 한다고 가정해 보겠습니다.

이를 위해 API 프록시에 두 개의 조건부 흐름인 /developers/apps를 추가합니다.

새 프록시 편집기

조건부 흐름을 추가하려면 다음 안내를 따르세요.

  1. 프록시 편집기에서 개발 탭을 선택합니다.
  2. 왼쪽 창에서 프록시 엔드포인트 > 기본값을 선택합니다.

    왼쪽 창에서 프록시 엔드포인트 > 기본값을 선택합니다.

  3. 응답 창 위에 있는 + 버튼을 클릭합니다.

    조건부 흐름 추가 버튼

  4. 조건부 흐름 추가 대화상자에 다음 구성을 입력합니다.
    • 흐름 이름: Developers
    • 조건 유형: Path
    • 경로: /developers

    조건부 흐름 추가 대화상자

    URI 끝에 /developers를 사용한 호출이 프록시에 전송되면 조건이 트리거되고 정책이 실행됩니다.

  5. 이제 /apps의 조건부 흐름을 추가하고 요청의 URI와 POST 동사 모두에 대해 조건을 트리거한다고 가정해 보겠습니다. 구성 과정에서 다음을 설정해야 합니다.
    • 흐름 이름: Apps
    • 조건 유형: Path and Verb
    • 경로: /apps
    • 동사: POST

    URI 끝에 /apps가 있고 POST 동사를 사용하는 호출이 프록시에 전송되면 조건이 트리거되고 정책이 실행됩니다.

추가된 흐름이 응답 창에 표시됩니다.

조건부 흐름 추가 대화상자

기본 프록시 편집기

API 프록시 편집기 탐색창의 개발 창에서 프록시 엔드포인트기본값 옆에 있는 를 클릭합니다.

기본값 옆에 있는 더하기 기호 위로 마우스 포인터를 가져가면 마우스 오버 텍스트에 &#39;새 흐름 추가&#39;가 표시됩니다.

새 조건부 흐름 창에서 다음 키 구성을 입력합니다.

  • 흐름 이름: Developers
  • 조건 유형: Path
  • 경로: /developers

새 조건부 흐름 창에서 개발자라고 표시된 흐름은 &#39;개발자 서비스에 등록된 앱 개발자&#39;라는 설명과 함께 구성됩니다.

URI 끝에 /developers를 사용한 호출이 프록시에 전송되면 조건이 트리거되고 정책이 실행됩니다.

이제 /apps의 조건부 흐름을 추가하고 요청의 URI와 POST 동사 모두에 대해 조건을 트리거한다고 가정해 보겠습니다. 구성 과정에서 다음을 설정해야 합니다.

  • 흐름 이름: Apps
  • 조건 유형: Path and Verb
  • 경로: /apps
  • 동사: POST

새 조건부 흐름 창에서 앱이라는 흐름은 &#39;개발자 서비스에 등록된 개발자 앱&#39;이라는 설명과 함께 구성됩니다.

URI 끝에 /apps가 있고 POST 동사를 사용하는 호출이 프록시에 전송되면 조건이 트리거되고 정책이 실행됩니다.

탐색창에 개발자에 대한 새로운 흐름이 표시됩니다.

앱 및 개발자에 대한 새 흐름은 프록시 엔드포인트 아래 탐색창에 표시됩니다.

흐름 중 하나를 선택하여 API 프록시 편집기 코드 보기에서 조건부 흐름 구성을 확인합니다.

<Flow name="Apps">
    <Description>Developer apps registered in Developer Services</Description>
    <Request/>
    <Response/>
    <Condition>(proxy.pathsuffix MatchesPath "/apps") and (request.verb = "POST")</Condition>
</Flow>

이와 같이 API 리소스는 인바운드 요청의 URI 경로를 평가하는 조건부 흐름입니다. (proxy.pathsuffix 변수는 ProxyEndpoint 구성에서 구성된 BasePath를 따르는 요청의 URI를 식별합니다.)

사용자가 정의한 각 API 리소스는 API 프록시에서 조건부 흐름으로 구현됩니다. (흐름 구성을 참조하세요.)

API 프록시를 테스트 환경에 배포하고 나면

http://example.com/PROXY_PATH/apps

위 요청에서 조건이 true로 평가되며, 이 흐름이 관련된 정책과 함께 실행됩니다.

다음 예시 조건은 자바 정규 표현식을 사용하여 후행 슬래시가 있거나 없는 /apps 리소스(/apps 또는 /apps/**)에 대한 호출을 인식합니다.

<Condition>(proxy.pathsuffix JavaRegex "/apps(/?)") and (request.verb = "POST")</Condition>

이러한 조건 유형에 대한 자세한 내용은 Apigee 커뮤니티...후행 '/' 존재 여부와 상관없이 일치시키는 방법을 참조하세요.

계층식 URI 모델링

경우에 따라 계층적 API 리소스가 있습니다. 예를 들어 Developer apps list API는 개발자에게 속한 모든 앱을 나열하는 메서드를 제공합니다. URI 경로는 다음과 같습니다.

/developers/DEVELOPER_EMAIL/apps

컬렉션의 각 항목에 고유 ID가 생성되며 때로는 다음과 같이 주석 처리되는 리소스가 있을 수 있습니다.

/genus/:id/species

이 경로는 다음 두 URI에 동일하게 적용됩니다.

/genus/18904/species
/genus/17908/species

API 리소스에서 이 구조를 표시하려면 와일드 카드를 사용하면 됩니다. 예를 들면 다음과 같습니다.

/developers/*/apps
/developers/*example.com/apps
/genus/*/species

계층식 URI가 API 리소스로 적절하게 확인됩니다.

특히 복잡한 계층식 API에서 특정 URI 프래그먼트 아래의 모든 항목을 확인해야 하는 경우가 있습니다. 이때는 리소스 정의에 이중 별표 와일드 카드를 사용합니다. 다음 API 리소스를 정의하는 경우를 예로 들겠습니다.

/developers/**

이 API 리소스는 다음 URI 경로를 확인합니다.

/developers/DEVELOPER_EMAIL/apps
/developers/DEVELOPER_EMAIL/keys
/developers/DEVELOPER_EMAIL/apps/APP_ID/keys

API 프록시 정의의 조건부 흐름 조건은 다음과 같습니다.

<Condition>(proxy.pathsuffix MatchesPath "/developers/**") and (request.verb = "POST")</Condition>

기타 예시

RouteRule에 연결된 조건

<RouteRule name="default">
  <!--this routing executes if the header indicates that this is an XML call. If true, the
    call is routed to the endpoint XMLTargetEndpoint-->
  <Condition>request.header.content-type = "text/xml"</Condition>
  <TargetEndpoint>XmlTargetEndpoint</TargetEndpoint>
</RouteRule>

정책에 연결된 조건

<Step>
  <!--the policy MaintenancePolicy only executes if the response status code is exactly 503 -->
  <Condition>response.status.code = 503</Condition>
  <Name>MaintenancePolicy</Name>
</Step>

Conditional Flow

<!-- this entire flow is executed only if the request verb is a GET-->
<Flow name="GetRequests">
  <Condition>request.verb="GET"</Condition>
  <Request>
    <Step>
<!-- this policy only executes if request path includes a term like statues-->
<Condition>request.path ~ "/statuses/**"</Condition>
      <Name>StatusesRequestPolicy</Name>
    </Step>
  </Request>
  <Response>
    <Step>
<!-- this condition has multiple expressions. The policy executes if the response code status is exactly 503 or 400-->
<Condition>(response.status.code = 503) or (response.status.code = 400)</Condition>
      <Name>MaintenancePolicy</Name>
    </Step>
  </Response>
</Flow>

조건의 샘플 연산자

다음은 조건을 만드는 데 사용되는 연산자의 예시입니다.

  • request.header.content-type = text/xml
  • request.header.content-length < 4096 && request.verb = PUT
  • response.status.code = 404 || response.status.code = 500
  • request.uri MatchesPath /*/statuses/**
  • request.queryparam.q0 NotEquals 10

실제 예시: 경로 끝에 있는 / 무시

Apigee 개발자는 일반적으로 경로 서픽스(/cat/cat/)를 모두 처리하려고 합니다. 일부 사용자 또는 클라이언트가 경로 끝에 슬래시를 추가하여 API를 호출할 수 있으며 조건문에서 이를 처리할 수 있어야 하기 때문입니다. 정확한 사용 사례는 URL의 후행 '/' 존재 여부와 상관없이 일치시키는 방법에서 다루고 있습니다.

원하는 경우 다음과 같이 정규식을 사용하지 않고 이 작업을 수행할 수 있습니다.

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Condition>(proxy.pathsuffix = "/cat") OR (proxy.pathsuffix = "/cat/")</Condition>
                <Name>SomePolicy</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

이 예시는 좋은 옵션으로서 명확하고 이해하기에 쉽습니다.

그러나 정규식을 사용하여 동일한 작업을 수행할 수 있습니다. 괄호는 문의 정규 표현식 부분을 그룹화하는 데 사용되지만 필수는 아닙니다.

<Condition>(proxy.pathsuffix JavaRegex "/cat(/?)"</Condition>

API 호출:

GET http://example.com/matchtest/cat
or
GET http://example.com/matchtest/cat/

정책이 실행되나요? 예. 정규 표현식에서 ? 문자는 0개 또는 1개의 선행 문자와 일치한다는 의미입니다. 따라서 /cat/cat/ 모두 일치합니다.

API 호출:

GET http://example.com/matchtest/cat/spotted

정책이 실행되나요? 아니요. 정규 표현식은 선행 문자의 어커런스 0개 또는 1개만 일치하며 다른 항목은 허용되지 않습니다.

JavaRegex를 사용한 임의 문자열 일치

이 주제의 모든 예시에서는 기본 제공되는 흐름 변수 중 하나인 proxy.pathsuffix와 일치시키는 방법을 보여줍니다. proxy.pathsuffix와 같이 기본 제공되는 흐름 변수인지 여부와 상관없이 임의 문자열 또는 흐름 변수에 패턴 일치를 수행할 수 있다는 점을 알고 있으면 유용합니다.

예를 들어 임의의 문자열, 백엔드 페이로드에서 반환된 문자열 또는 인증 서버 조회에서 반환된 문자열을 테스트하는 조건이 있는 경우, 일치 연산자를 사용하여 테스트할 수 있습니다. JavaRegex를 사용하는 경우 정규 표현식이 전체 제목 문자열과 비교됩니다. 제목이 abc이고 정규 표현식이 [a-z]인 경우 [a-z]가 정확히 하나의 알파벳 문자와 일치하기 때문에 일치 항목이 없습니다. [a-z]+ 표현식은 [a-z]*[a-z]{3}처럼 작동합니다.

간단한 예를 살펴보겠습니다. 인증 서버가 역할 목록을 쉼표로 구분된 문자열(예: editor, author, guest)로 반환하는 경우를 가정해 보겠습니다.

편집자 역할이 있는지 테스트하는 다음 구조는 editor가 전체 문자열의 일부이기 때문에 작동하지 않습니다.

<Condition>returned_roles ~~ "editor"</Condition>

하지만 다음 구조는 작동합니다.

<Condition>returned_roles ~~ ".*\beditor\b.*")</Condition>

.* 프리픽스와 서픽스를 사용하여 문자열의 모든 공백과 다른 부분을 고려하기 때문에 작동합니다.

이 예시에서는 Matches 연산자로 editor를 테스트할 수도 있습니다.

<Condition>returned_roles ~~ "*editor*")</Condition>

하지만 더 높은 정밀도가 필요한 경우에는 JavaRegex를 선택하는 것이 좋습니다.

JavaRegex 표현식에서 큰따옴표 이스케이프 처리

조건 구문에서는 JavaRegex 표현식을 큰따옴표로 묶어야 합니다. 따라서 큰따옴표가 포함된 정규 표현식의 경우 이를 일치시킬 다른 방법이 필요합니다. 즉, 이때는 유니코드를 사용합니다. 예를 들어 다음과 같이 큰따옴표가 포함된 헤더를 전달한다고 가정해 보겠습니다.

 -H 'content-type:multipart/related; type="application/xop+xml"'

정규식 조건에서 해당 헤더를 일치시키려고 하면 표현식에 큰따옴표가 포함되어 있으므로 Invalid Condition 오류가 발생합니다.

request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"

해결책은 ASCII 기반 큰따옴표를 유니코드에 해당하는 \u0022로 바꾸는 것입니다. 예를 들어 다음 표현식은 유효하고 올바른 결과를 생성합니다.

request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"