Các điều kiện có biến luồng

Bạn đang xem tài liệu về Apigee Edge.
Chuyển đến tài liệu về Apigee X.
thông tin

Câu lệnh có điều kiện là cấu trúc điều khiển phổ biến trong tất cả các ngôn ngữ lập trình. Giống như ngôn ngữ lập trình, cấu hình proxy API hỗ trợ các câu lệnh có điều kiện cho Luồng, Chính sách, Bước và Quy tắc định tuyến. Bằng cách xác định các câu lệnh có điều kiện, bạn xác định hành vi động cho API của mình. Hành vi động này cho phép bạn làm những việc như chuyển đổi XML thành JSON chỉ dành cho thiết bị di động hoặc định tuyến đến một URL phụ trợ dựa trên loại nội dung hoặc động từ HTTP của thông báo yêu cầu.

Chủ đề này hướng dẫn bạn cách sử dụng các điều kiện để áp dụng linh động các tính năng quản lý API trong thời gian chạy mà không cần viết mã.

Định cấu hình câu lệnh có điều kiện

Hành vi có điều kiện được triển khai trong proxy API bằng cách sử dụng kết hợp conditionsconditions. Câu lệnh có điều kiện được tạo bằng phần tử Điều kiện. Sau đây là một điều kiện trống:

<Condition></Condition>

Để tạo câu lệnh có điều kiện, bạn thêm toán tử có điều kiện và biến để tạo cấu trúc sau:

<Condition>{variable.name}{operator}{"value"}</Condition>

Các toán tử có điều kiện được hỗ trợ bao gồm = (bằng), != (không bằng) và > (lớn hơn). Để dễ đọc, bạn cũng có thể viết các điều kiện dưới dạng văn bản: equals, notequals, greaterthan.

Khi làm việc với các đường dẫn URI, bạn có thể sử dụng ~/ hoặc MatchesPath. Bạn cũng có thể so khớp biểu thức chính quy JavaRegex với toán tử ~~.

Các điều kiện được dùng để xác định luồng có điều kiện của proxy API cho các tài nguyên API phụ trợ, như mô tả trong bài viết Tạo luồng có điều kiện cho tài nguyên API phụ trợ. Để biết danh sách đầy đủ các điều kiện, hãy xem phần Tài liệu tham khảo về điều kiện.

Biến

Các điều kiện thực hiện công việc của chúng bằng cách đánh giá giá trị của biến. Biến là thuộc tính của giao dịch HTTP do proxy API thực thi hoặc thuộc tính của chính cấu hình proxy API. Bất cứ khi nào một proxy API nhận được yêu cầu từ một ứng dụng, Apigee Edge sẽ điền một danh sách dài gồm các biến liên quan đến những yếu tố như thời gian hệ thống, thông tin mạng của ứng dụng, tiêu đề HTTP trên thông báo, cấu hình proxy API, quá trình thực thi chính sách, v.v. Thao tác này tạo ra một ngữ cảnh phong phú mà bạn có thể dùng để thiết lập câu lệnh có điều kiện.

Biến luôn sử dụng ký hiệu dấu chấm. Ví dụ: tiêu đề HTTP trên thông báo yêu cầu được cung cấp dưới dạng các biến tên là request.header.{header_name}. Vì vậy, để đánh giá tiêu đề Loại nội dung, bạn có thể sử dụng biến request.header.Content-type. Ví dụ: request.header.Content-type = "application/json" cho biết rằng loại nội dung của yêu cầu phải có định dạng JSON.

Giả sử bạn cần tạo một câu lệnh có điều kiện để chỉ thực thi chính sách khi thông báo yêu cầu là một GET. Để tạo một điều kiện giúp đánh giá động từ HTTP của một yêu cầu, bạn hãy tạo câu lệnh có điều kiện dưới đây. Biến trong điều kiện này là request.verb. Giá trị của biến là GET. Toán tử là =.

<Condition>request.verb = "GET"</Condition>
Bạn cũng có thể sử dụng:
<Condition>request.verb equals "GET"</Condition>

Edge sử dụng một câu lệnh như vậy để đánh giá các điều kiện. Ví dụ trên đánh giá là true nếu động từ HTTP liên kết với yêu cầu là GET. Nếu động từ HTTP liên kết với yêu cầu là POST, thì câu lệnh sẽ có giá trị là false.

Để bật hành vi động, bạn có thể đính kèm Điều kiện vào Luồng, Bước và Quy tắc định tuyến.

Khi đính kèm một điều kiện vào một Luồng, bạn sẽ tạo một "Luồng có điều kiện". Luồng có điều kiện chỉ thực thi khi điều kiện được đánh giá là true (đúng). Bạn có thể đính kèm số lượng Chính sách mà bạn muốn vào một Luồng có điều kiện. Luồng có điều kiện cho phép bạn tạo các quy tắc xử lý có tính chuyên biệt cao đối với các thông báo yêu cầu hoặc phản hồi đáp ứng một số tiêu chí nhất định.

Ví dụ: để tạo một Flow chỉ thực thi khi động từ yêu cầu là một GET:

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

Cách tạo một Luồng (Flow) cho GET và một Luồng khác cho POST:

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

Như trong ví dụ bên dưới, bạn có thể áp dụng điều kiện cho Bước chính sách. Điều kiện sau khiến Chính sách VerifyApiKey được thực thi chỉ khi thông báo yêu cầu là một yêu cầu POST.

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

Sau khi xác định các Luồng có điều kiện như vậy, bạn có thể đính kèm Chính sách với các Luồng có điều kiện đó, bật proxy API để thực thi một nhóm chính sách cho các yêu cầu GET và một nhóm chính sách khác cho các yêu cầu POST.

Để có thông tin tham khảo đầy đủ, hãy xem các tài nguyên sau:

Ví dụ 1

Ví dụ sau đây cho thấy một luồng có điều kiện có tên Convert-for-devices, được định cấu hình trong luồng phản hồi ProxyEndpoint. Thêm Điều kiện dưới dạng một phần tử cho thực thể áp dụng điều kiện đó. Trong ví dụ này, điều kiện là một thành phần của luồng. Do đó, luồng sẽ thực thi bất cứ khi nào câu lệnh được đánh giá là true (đúng).

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

Đối với mỗi yêu cầu nhận được từ một ứng dụng, Edge lưu trữ giá trị của tất cả tiêu đề HTTP xuất hiện dưới dạng biến. Nếu yêu cầu chứa tiêu đề HTTP có tên là User-Agent, thì tiêu đề đó và giá trị của tiêu đề đó sẽ được lưu trữ dưới dạng một biến có tên là request.header.User-Agent.

Do cấu hình ProxyEndpoint ở trên, Edge sẽ kiểm tra giá trị của biến request.header.User-Agent để xem điều kiện có được đánh giá là đúng hay không.

Nếu điều kiện được đánh giá là đúng, tức là giá trị của biến request.header.User-Agent bằng Mozilla, thì Luồng có điều kiện sẽ thực thi và chính sách XMLtoJSON có tên là ConvertToJSON sẽ được thực thi. Nếu không, Flow không được thực thi và phản hồi XML sẽ được trả về chưa sửa đổi (ở định dạng XML) cho ứng dụng yêu cầu.

Ví dụ 2

Hãy dùng một ví dụ cụ thể, trong đó bạn cần chuyển đổi thông báo phản hồi từ XML thành JSON (nhưng chỉ dành cho thiết bị di động). Trước tiên, hãy tạo chính sách sẽ chuyển đổi phản hồi ở định dạng XML từ API thời tiết thành JSON:

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

Cấu hình chính sách ở trên yêu cầu proxy API nhận thông báo phản hồi, thực hiện hoạt động chuyển đổi từ XML sang JSON với các chế độ cài đặt mặc định, sau đó ghi kết quả vào thông báo phản hồi mới. (Nếu đang chuyển đổi một thông báo yêu cầu từ XML sang JSON, bạn chỉ cần đặt cả hai giá trị này thành request.)

Vì muốn chuyển đổi phản hồi từ XML sang JSON, bạn cần định cấu hình Luồng phản hồi có điều kiện để thực hiện việc chuyển đổi. Ví dụ: để chuyển đổi tất cả phản hồi từ XML sang JSON trước khi các phản hồi đó được trả về ứng dụng, hãy định cấu hình Luồng phản hồi ProxyEndpoint sau đây.

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

Khi bạn gọi API bằng yêu cầu thông thường, phản hồi sẽ được định dạng trong JSON.

Tuy nhiên, mục tiêu của bạn là chỉ chuyển đổi Báo cáo thời tiết thành JSON khi ứng dụng yêu cầu là một thiết bị di động. Để cho phép hành vi động như vậy, bạn phải thêm câu lệnh có điều kiện vào Flow.

Kiểm thử luồng có điều kiện

Trong yêu cầu mẫu này, tiêu đề HTTP User-Agent được đặt thành Mozilla, khiến câu lệnh có điều kiện được đánh giá thành true và luồng có điều kiện Convert-for-devices sẽ thực thi.

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

hoặc để in đẹp mắt ở những nơi có sẵn Python:

$ curl -H "User-Agent:Mozilla" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282 | python -mjson.tool

Câu trả lời mẫu:

. . .

"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"
          }
      ]
  }

. . .

Yêu cầu được gửi không có tiêu đề User-Agent hoặc có giá trị khác với Mozilla, sẽ dẫn đến phản hồi có định dạng XML.

$ curl http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

Phản hồi XML chưa sửa đổi sẽ được trả về.

Câu trả lời mẫu:

<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" />

Phương thức khớp mẫu

Phần này mô tả cách sử dụng tính năng so khớp mẫu có các điều kiện trong quy trình Apigee.

Toán tử

Phần này mô tả cách sử dụng các toán tử so khớp mẫu sau đây trong câu lệnh có điều kiện:

Khớp với

Trước tiên, hãy xem toán tử có điều kiện "Match" (Khớp) hoặc "~". Hai toán tử này giống nhau -- phiên bản tiếng Anh, "Match" (So khớp) được coi là một tuỳ chọn dễ đọc hơn.

Tóm tắt: Toán tử "Kết quả trùng khớp" cung cấp cho bạn 2 khả năng. Hãy khớp chuỗi theo nghĩa đen hoặc khớp ký tự đại diện với "*". Như bạn có thể thấy, ký tự đại diện sẽ khớp với số không hoặc nhiều ký tự. Hãy xem cách này hoạt động.

XML sau đây cho thấy điều kiện Bước. Hàm này thực thi chính sách SomePolicy khi điều kiện được đánh giá là true (đúng). Trong ví dụ này, chúng tôi sẽ kiểm thử biến proxy.pathsuffix. Đây là một biến được tích hợp sẵn trong Edge lưu trữ hậu tố đường dẫn của yêu cầu. Tuy nhiên, hãy lưu ý rằng bạn có thể kiểm thử giá trị của bất kỳ biến luồng nào chứa chuỗi. Vì vậy, trong trường hợp này, nếu đường dẫn cơ sở của yêu cầu đến là /animals và yêu cầu là /animals/cat, thì hậu tố đường dẫn sẽ là chuỗi giá trị cố định "/cat".

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

Câu hỏi: Hậu tố đường dẫn proxy nào sẽ khiến SomePolicy thực thi? Chỉ có một khả năng.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Có, vì hậu tố của đường dẫn proxy khớp chính xác với "/cat". Lệnh này sẽ không thực thi nếu hậu tố là /bat, /dog hay "/" hoặc bất kỳ giá trị nào khác.

Bây giờ, hãy xem xét câu lệnh có điều kiện sau đây khi chúng ta sử dụng ký tự đại diện "*":

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Có, vì ký tự đại diện khớp với ký tự bất kỳ và "/cat" là kết quả trùng khớp.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/bat

Chính sách có thực thi không? Có, vì ký tự đại diện khớp với ký tự bất kỳ, nên "/bat" là kết quả khớp.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/owl

Chính sách có thực thi không? Chắc chắn là không. Mặc dù ký tự đại diện khớp với "o", nhưng chữ cái "wl" lại không khớp.

Bây giờ, hãy di chuyển ký tự đại diện đến cuối hậu tố:

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Có, vì ký tự đại diện khớp với không hoặc nhiều ký tự bất kỳ.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/bat

Chính sách có thực thi không? Không, "/bat" không khớp.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat123

Chính sách có thực thi không? Có, ký tự đại diện khớp với 0 hoặc nhiều ký tự bất kỳ, do đó "123" tạo ra kết quả khớp.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat/bird/mouse

Chính sách có thực thi không? Có, vì ký tự đại diện khớp với 0 hoặc nhiều ký tự bất kỳ, nên "/bird/mouse" tạo ra kết quả khớp. Hãy lưu ý rằng biểu thức như thế này có thể khiến bạn gặp rắc rối vì biểu thức này khớp với mọi thứ sau các ký tự cố định!

Câu hỏi: Toán tử So khớp có phân biệt chữ hoa chữ thường không?

Có. Giả sử bạn có tình trạng như sau:

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Không, ký tự đại diện khớp với mọi chữ cái (bất kể cách viết hoa) nhưng chữ "a" viết thường không khớp với "A".

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/bAt

Chính sách có thực thi không? Có, trường hợp này khớp.

Câu hỏi: Làm cách nào để thoát các ký tự bằng toán tử So khớp?

Sử dụng ký tự phần trăm "%" để thoát các ký tự dành riêng. Ví dụ:

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Không, toán tử So khớp đang tìm chuỗi giá trị cố định "c*at".

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/c*at

Câu hỏi:Chính sách có thực thi không?

Có, đường dẫn này, mặc dù hơi khác thường, phù hợp.

JavaRegex

Như bạn có thể thấy, toán tử "Khớp" rất phù hợp với các trường hợp đơn giản. Tuy nhiên, bạn có thể sử dụng một toán tử khác, toán tử "JavaRegex" hoặc "~~". Hai toán tử này là cùng một toán tử, ngoại trừ JavaRegex được coi là dễ đọc hơn. Lớp này có tên là JavaRegex vì cho phép so khớp mẫu biểu thức chính quy và Edge tuân theo các quy tắc tương tự như các lớp trong gói java.util.regex bằng ngôn ngữ Java. Cách hoạt động của toán tử JavaRegex rất khác với toán tử So khớp, vì vậy, bạn không nên nhầm lẫn hai toán tử này!

Tóm tắt: Toán tử "JavaRegex" cho phép bạn sử dụng cú pháp biểu thức chính quy trong các câu lệnh có điều kiện.

Mã sau đây cho thấy điều kiện Bước. Hàm này sẽ thực thi chính sách SomePolicy nếu điều kiện được đánh giá là true (đúng). Trong ví dụ này, chúng tôi kiểm thử biến proxy.pathsuffix. Đây là một biến được tích hợp sẵn trong Edge lưu trữ hậu tố đường dẫn của yêu cầu. Nếu đường dẫn cơ sở của yêu cầu đến là /animals và yêu cầu là /animals/cat, thì hậu tố của đường dẫn sẽ là chuỗi giá trị cố định "/cat".

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

Câu hỏi: Hậu tố đường dẫn proxy nào sẽ khiến SomePolicy thực thi? Giống như với toán tử So khớp, chỉ có một khả năng trong trường hợp này.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Có, vì hậu tố của đường dẫn proxy khớp chính xác với "/cat". Phương thức này sẽ không thực thi nếu hậu tố là /bat hoặc /dog hoặc bất kỳ giá trị nào khác.

Bây giờ, hãy tạo một biểu thức chính quy bằng bộ định lượng "*". Bộ định lượng này khớp với 0 hoặc nhiều ký tự trước đó.

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Không đâu! Bộ định lượng "*" khớp với 0 hoặc nhiều ký tự trước, tức là "c".

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/ccccct

Chính sách có thực thi không? Có, vì ký tự đại diện khớp với 0 hoặc nhiều ký tự trước đó.

Tiếp theo, chúng ta sử dụng bộ định lượng "?" để so khớp với ký tự trước đó một lần hoặc hoàn toàn không so khớp với ký tự trước đó.

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Có. Bộ định lượng "?" khớp với 0 hoặc một lần xuất hiện của ký tự trước, đó là "a".

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/ct

Chính sách có thực thi không? Có. Bộ định lượng "?" khớp với một hoặc không có ký tự nào trước đó. Trong trường hợp này, không có ký tự "a", do đó, điều kiện sẽ được đánh giá là true (đúng).

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/caat

Chính sách có thực thi không? Không. Bộ định lượng "?" khớp với một trong ký tự trước đó, tức là "a".

Tiếp theo, chúng ta sử dụng kiểu "[abc]" hoặc "nhóm" của biểu thức biểu thức chính quy. Giá trị này khớp với các ký tự "a", "b" hoặc "c".

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Có. Chúng tôi đang sử dụng biểu thức chính quy ở đây và biểu thức "[cbr]" khớp với một "c", "b" HOẶC "r". Những lệnh gọi này cũng khớp:

GET http://artomatic-test.apigee.net/matchtest/bat

GET http://artomatic-test.apigee.net/matchtest/rat

Nhưng đây không phải là kết quả phù hợp:

GET http://artomatic-test.apigee.net/matchtest/mat

Câu hỏi: Toán tử JavaRegex có phân biệt chữ hoa chữ thường không?

Có. Giả sử bạn có tình trạng như sau:

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat

Chính sách có thực thi không? Có, biểu thức chính quy khớp với 0 hoặc một trong các ký tự trước đó (là "a").

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cAt

Câu hỏi: Chính sách có thực thi không?

Không, vì chữ "A" viết hoa không khớp với chữ "a" viết thường.

MatchesPath

Bạn cũng có thể chỉ định toán tử MatchesPath như sau "~/". Các toán tử này khá giống với toán tử Matches (~) và JavaRegex (~~). Tuy nhiên, matchPath lại hoàn toàn khác.

Hãy nhớ rằng toán tử này xem đường dẫn dưới dạng một chuỗi các phần. Do đó, nếu đường dẫn là: /animals/cats/wild, bạn có thể coi đường dẫn đó bao gồm các phần "/animals", "/cats" và "/wild".

Toán tử MatchesPath cho phép bạn sử dụng 2 ký hiệu ký tự đại diện: một dấu hoa thị (*) và một dấu hoa thị kép (**). Chỉ một dấu hoa thị khớp với một phần tử đường dẫn. Dấu hoa thị kép khớp với một hoặc nhiều phần tử đường dẫn.

Hãy xem một ví dụ. Trong ví dụ này, chúng tôi sẽ kiểm thử biến proxy.pathsuffix, một biến được tích hợp sẵn trong Edge lưu trữ hậu tố đường dẫn của yêu cầu. Tuy nhiên, hãy lưu ý rằng bạn có thể kiểm thử giá trị của bất kỳ biến luồng nào có chứa chuỗi.

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

Câu hỏi: Hậu tố đường dẫn proxy nào sẽ khiến SomePolicy thực thi?

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/animals

Câu hỏi: Chính sách có thực thi không?

Không, vì điều kiện yêu cầu một phần tử đường dẫn khác sau "/animals", như được chỉ định bằng "/*".

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/animals/

Chính sách có thực thi không? Có, đường dẫn có một thành phần đường dẫn khác (phần sau "/animals/"), nhưng đường dẫn này chỉ trống.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats

Chính sách có thực thi không? Có, vì đường dẫn rõ ràng có một phần tử ("/cats") đứng sau "/animals"

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

Câu hỏi: Chính sách có thực thi không?

Không, vì một dấu hoa thị chỉ khớp với một phần tử đường dẫn và API này có nhiều phần tử sau "/animals".

Giờ hãy sử dụng dấu hoa thị kép:

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

Câu hỏi: Hậu tố đường dẫn proxy nào sẽ khiến SomePolicy thực thi?

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/animals

Chính sách có thực thi không? Không, vì điều kiện yêu cầu ít nhất một phần tử đường dẫn sau đây do "/**" chỉ định.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/animals/

Chính sách này có thực thi không?

Có, đường dẫn có một thành phần đường dẫn khác (phần sau "/animals/"), nhưng đường dẫn này chỉ trống.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats

Chính sách này có thực thi không?

Có, vì đường dẫn có ít nhất một phần tử đứng sau "/animals"

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild

Chính sách này có thực thi không?

Có, vì đường dẫn có nhiều phần tử đứng sau "/animals"

Kết hợp các dấu hoa thị

Bạn có thể sử dụng kết hợp dấu hoa thị đơn (*) và kép (**) để tinh chỉnh thêm việc so khớp đường dẫn.

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

Lệnh gọi API:

Tất cả các lệnh gọi API này sẽ tạo ra kết quả trùng khớp:

GET http://artomatic-test.apigee.net/matchtest/animals/cats/wild/

GET http://artomatic-test.apigee.net/matchtest/animals/dogs/wild/austrailian



GET http://artomatic-test.apigee.net/matchtest/animals/birds/wild/american/finches

Tài nguyên API

Dịch vụ RESTful là tập hợp các tài nguyên API. Tài nguyên API là một mảnh đường dẫn URI giúp xác định một số thực thể mà nhà phát triển có thể truy cập bằng cách gọi API của bạn. Ví dụ: nếu dịch vụ của bạn cung cấp báo cáo thời tiết và thông tin dự báo thời tiết, thì dịch vụ phụ trợ của bạn có thể xác định 2 tài nguyên API:

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

Khi tạo proxy API (như minh hoạ trong phần Tạo proxy API đầu tiên), thì ít nhất bạn cũng phải tạo một URL cơ sở đại diện liên kết đến dịch vụ phụ trợ của bạn. Ví dụ:

URL cơ sở phụ trợ URL proxy API mới/tương đương
http://mygreatweatherforecast.com http://{your_org}-{environment}.apigee.net/mygreatweatherforecast

Tại thời điểm này, bạn có thể thực hiện lệnh gọi API đến phần phụ trợ của mình bằng cách sử dụng URL cơ sở. Nhưng khi bạn sử dụng URL proxy API, mọi thứ sẽ bắt đầu trở nên thú vị.

Ngoài số liệu phân tích API mà Edge bắt đầu thu thập khi bạn sử dụng proxy API, proxy cũng cho phép bạn xác định các luồng có điều kiện liên kết với các tài nguyên trên phần phụ trợ của bạn. Về cơ bản, "Nếu một lệnh gọi GET đến tài nguyên /báo cáo, thì Edge sẽ phải thực hiện một hành động nào đó."

Hình ảnh sau đây cho thấy sự khác biệt về hành vi giữa 2 URL cuối cùng truy cập vào cùng một phần phụ trợ. Một là URL tài nguyên chưa được proxy, thẻ còn lại là proxy API Edge có luồng có điều kiện đến cùng một tài nguyên phụ trợ. Chúng tôi sẽ mô tả chi tiết hơn về các luồng có điều kiện ở bên dưới.

Cách các proxy API ánh xạ đến các tài nguyên phụ trợ cụ thể

Với một URL proxy API được liên kết tới URL cơ sở của dịch vụ phụ trợ (khi bạn tạo proxy), bạn có thể thêm luồng có điều kiện vào tài nguyên cụ thể, chẳng hạn như tài nguyên /reports/forecasts đề cập trước đó.

Giả sử bạn muốn yêu cầu Edge "làm gì đó" khi các lệnh gọi đến tài nguyên /reports hoặc /forecasts. Hiện tại, bạn chưa cần cho Edge biết việc cần làm, mà chỉ cần theo dõi các lệnh gọi đến các tài nguyên đó. Bạn thực hiện việc này với các điều kiện. Trong proxy API Edge, bạn có thể tạo các luồng có điều kiện cho /reports/forecasts. Đối với mục đích khái niệm, tệp XML của proxy API sau đây sẽ cho thấy các điều kiện đó.

<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>

Những điều kiện đó có nội dung như sau: "Khi một yêu cầu GET đến với /reports/forecasts trong URL, Edge sẽ làm bất cứ điều gì mà bạn (nhà phát triển API) yêu cầu, thông qua các chính sách bạn đính kèm với các quy trình đó.

Sau đây là một ví dụ về việc cho Edge biết việc cần làm khi đáp ứng một điều kiện. Trong XML proxy API sau đây, khi một yêu cầu GET được gửi đến https://yourorg-test.apigee.net/mygreatweatherforecast/reports, Edge sẽ thực thi chính sách "XML-to-JSON-1" trong phản hồi.

<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>

Ngoài các luồng có điều kiện không bắt buộc đó, mỗi proxy API cũng có 2 luồng mặc định: một <PreFlow> được thực thi trước các luồng có điều kiện và một <PostFlow> được thực thi sau các luồng có điều kiện. Các hàm này rất hữu ích để thực thi các chính sách khi bất kỳ lệnh gọi nào được thực hiện tới một proxy API. Ví dụ: nếu muốn xác minh khoá API của một ứng dụng cho mỗi lệnh gọi, bất kể tài nguyên phụ trợ được truy cập là gì, bạn có thể đặt chính sách Xác minh khoá API vào <PreFlow>. Để biết thêm thông tin về luồng, hãy xem phần Định cấu hình luồng.

Tạo luồng có điều kiện đến tài nguyên phụ trợ

Bạn không bắt buộc phải xác định các luồng có điều kiện cho tài nguyên phụ trợ trong proxy API. Tuy nhiên, các luồng có điều kiện đó cho phép bạn áp dụng hoạt động quản lý và giám sát một cách chi tiết.

Bạn sẽ có thể:

  • Áp dụng quy trình quản lý theo cách phản ánh ngữ nghĩa của mô hình API
  • Áp dụng chính sách và hành vi theo tập lệnh cho các đường dẫn tài nguyên (URI) riêng lẻ
  • Thu thập chỉ số chi tiết cho Dịch vụ Analytics

Ví dụ: giả sử bạn cần áp dụng nhiều loại logic cho các tài nguyên /developers cho /apps trong phần phụ trợ.

Để thực hiện việc này, bạn cần thêm 2 luồng có điều kiện vào proxy API: /developers/apps.

Trong chế độ xem Phát triển của ngăn Trình điều hướng của trình chỉnh sửa proxy API, nhấp vào biểu tượng dấu + bên cạnh giá trị mặc định trong Điểm cuối proxy.

Trong cửa sổ "Luồng có điều kiện mới", bạn nhập các cấu hình khoá sau:

  • Tên quy trình: Nhà phát triển
  • Loại điều kiện: Đường dẫn
  • Đường dẫn: /developers

Điều kiện sẽ được kích hoạt (và các chính sách sẽ được thực thi) nếu lệnh gọi được gửi tới proxy với /developers ở cuối URI.

Bây giờ, hãy thêm một luồng có điều kiện cho /apps và giả sử bạn muốn điều kiện đó được kích hoạt trên cả URI và động từ POST trong một yêu cầu. Cấu hình này bao gồm việc cài đặt những nội dung sau:

  • Tên quy trình: Ứng dụng
  • Loại điều kiện: Đường dẫn và Động từ
  • Đường dẫn: /apps
  • Động từ: POST

Điều kiện này sẽ được kích hoạt (và các chính sách sẽ được thực thi) nếu một lệnh gọi được gửi tới proxy có chứa /apps ở cuối URI và một động từ POST.

Trong ngăn Trình điều hướng, bạn sẽ thấy các luồng mới cho Ứng dụngNhà phát triển.

Chọn một trong các luồng để xem cấu hình luồng có điều kiện trong chế độ xem mã của trình chỉnh sửa proxy 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>

Như bạn có thể thấy, tài nguyên API chỉ đơn giản là Luồng có điều kiện, giúp đánh giá đường dẫn URI của yêu cầu đến. (Biến proxy.pathsuffix xác định URI của yêu cầu tuân theo BasePath đã định cấu hình trong cấu hình ProxyEndpoint.)

Mỗi tài nguyên API mà bạn xác định sẽ được triển khai bằng một Luồng có điều kiện trong proxy API. (Xem phần Định cấu hình quy trình.)

Sau khi bạn triển khai proxy API cho môi trường kiểm thử, hãy thực hiện yêu cầu sau:

http://{org_name}-test.apigee.net/{proxy_path}/apps

sẽ khiến điều kiện được đánh giá thành true (đúng) và quy trình này, cùng với mọi chính sách liên quan, sẽ được thực thi.

Điều kiện ví dụ sau đây sử dụng biểu thức chính quy Java để nhận ra các lệnh gọi được thực hiện đến tài nguyên /apps có hoặc không có dấu gạch chéo lên (/apps hoặc /apps/**):

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

Để biết thêm về loại tình trạng này, hãy xem phần Cách so khớp bất kể ... trong Cộng đồng API.

Lập mô hình URI phân cấp

Trong một số trường hợp, bạn sẽ có tài nguyên API phân cấp. Ví dụ: API Dịch vụ dành cho nhà phát triển cung cấp một phương thức để liệt kê tất cả các ứng dụng thuộc về một nhà phát triển. Đường dẫn URI là:

/developers/{developer_email}/apps

Bạn có thể có các tài nguyên mà trong đó mỗi thực thể trong một tập hợp sẽ có một mã nhận dạng duy nhất được tạo. Những tài nguyên này đôi khi được chú thích như sau:

/genus/:id/species

Đường dẫn này áp dụng như nhau cho 2 URI sau:

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

Để thể hiện cấu trúc này trong tài nguyên API, bạn có thể sử dụng ký tự đại diện. Ví dụ:

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

sẽ phân giải các URI phân cấp này dưới dạng tài nguyên API một cách thích hợp.

Trong một số trường hợp, đặc biệt là đối với các API phân cấp sâu, bạn có thể chỉ muốn phân giải mọi thứ bên dưới một mảnh URI nhất định. Để thực hiện việc này, hãy sử dụng ký tự đại diện đôi dấu hoa thị trong định nghĩa tài nguyên. Ví dụ: nếu bạn xác định tài nguyên API sau:
/developers/**

Tài nguyên API đó sẽ phân giải các đường dẫn URI sau:

/developers/{developer_email}/apps
/developers/{developer_email}/keys
/developers/{developer_email}/apps/{app_id}/keys

Sau đây là ví dụ minh hoạ điều kiện luồng có điều kiện trong phần định nghĩa proxy API:

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

Ví dụ khác

Điều kiện được đính kèm với 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>

Điều kiện có liên quan đến một chính sách

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

Luồng có điều kiện

<!-- 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>

Toán tử mẫu trong điều kiện

Dưới đây là một số ví dụ về các toán tử dùng để tạo điều kiện:

  • 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

Một ví dụ thực tế: Bỏ qua "/" ở cuối đường dẫn

Các nhà phát triển cạnh thường muốn xử lý cả hai hậu tố trong đường dẫn sau: "/cat" và "/cat/". Nguyên nhân là do một số người dùng hoặc ứng dụng có thể gọi API của bạn bằng thêm dấu gạch chéo ở cuối đường dẫn. Bạn cần xử lý được việc đó trong các câu lệnh có điều kiện. Trường hợp sử dụng chính xác này đã được thảo luận trên Cộng đồng Apigee.

Nếu muốn, bạn có thể đạt được điều này mà không cần sử dụng Biểu thức chính quy như sau:

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

Đây là một lựa chọn phù hợp. Chữ này phải rõ ràng và dễ đọc.

Tuy nhiên, bạn có thể thực hiện điều tương tự với Regex như thế này. Dấu ngoặc đơn được dùng để nhóm phần biểu thức chính quy của câu lệnh (nhưng không bắt buộc).

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

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat
or

GET http://artomatic-test.apigee.net/matchtest/cat/

Chính sách có thực thi không? Có. Lưu ý rằng trong một biểu thức chính quy, ký tự "?" có nghĩa là: khớp với 0 hoặc một trong các ký tự trước đó. Do đó, cả "/cat" và "/cat/" đều khớp.

Lệnh gọi API:

GET http://artomatic-test.apigee.net/matchtest/cat/spotted

Chính sách có thực thi không? Không. Biểu thức chính quy khớp với 0 hoặc chỉ một lần xuất hiện của ký tự trước đó và bạn không được phép xuất hiện nội dung nào khác.

So khớp chuỗi tuỳ ý với JavaRegex

Trong tất cả ví dụ trong chủ đề này, chúng tôi sẽ chỉ ra cách so khớp với một trong các biến luồng tích hợp sẵn: proxy.pathsuffix. Bạn nên biết rằng bạn có thể thực hiện so khớp mẫu trên bất kỳ biến luồng hoặc chuỗi tùy ý nào, cho dù đó có phải là biến luồng tích hợp sẵn như proxy.pathsuffix hay không.

Chẳng hạn, nếu bạn có một điều kiện kiểm thử một chuỗi tuỳ ý, có thể là một chuỗi được trả về trong tải trọng phụ trợ hoặc một chuỗi được trả về từ quá trình tra cứu máy chủ xác thực, thì bạn có thể dùng các toán tử phù hợp để kiểm tra chuỗi đó. Nếu bạn sử dụng JavaRegex, biểu thức chính quy sẽ được so sánh với toàn bộ chuỗi chủ đề. Nếu tiêu đề là "abc" và biểu thức chính quy là "[a-z]", thì không có kết quả khớp nào vì "[a-z]" khớp chính xác với một ký tự alpha. Biểu thức "[a-z]+" hoạt động tương tự như "[a-z]*" và "[a-z]{3}.

Hãy xem một ví dụ cụ thể. Giả sử máy chủ xác thực trả về danh sách vai trò ở dạng một chuỗi được phân tách bằng dấu phẩy: "editor, creator, guest".

Để kiểm tra sự hiện diện của vai trò người chỉnh sửa, cấu trúc này sẽ không hoạt động vì "trình chỉnh sửa" chỉ là một phần của toàn bộ chuỗi.

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

Tuy nhiên, cấu trúc này sẽ hoạt động:

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

Phương pháp này hiệu quả vì có tính đến phần ngắt từ và mọi phần khác của chuỗi có tiền tố và hậu tố .*.

Trong ví dụ này, bạn cũng có thể kiểm thử "Editor" bằng toán tử So khớp:

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

Tuy nhiên, trong trường hợp bạn cần độ chính xác cao hơn, thì JavaRegex thường là lựa chọn tốt hơn.

Thoát dấu ngoặc kép trong biểu thức JavaRegex

Cú pháp Điều kiện yêu cầu một biểu thức JavaRegex phải được đặt trong dấu ngoặc kép; do đó, nếu có một biểu thức chính thức bao gồm dấu ngoặc kép, bạn cần một cách thay thế để so khớp với các biểu thức đó. Câu trả lời là Unicode. Ví dụ: giả sử bạn truyền vào một tiêu đề có dấu ngoặc kép như sau:
 -H 'content-type:multipart/related; type="application/xop+xml"'
Nếu cố gắng so khớp tiêu đề đó trong điều kiện Regex, bạn sẽ gặp lỗi Điều kiện không hợp lệ vì biểu thức có chứa dấu ngoặc kép:
request.header.Content-Type ~~ "(multipart\/related)(; *type="application\/xop\+xml\")"
Giải pháp là thay thế dấu ngoặc kép dựa trên ASCII bằng dấu ngoặc kép tương đương Unicode, \u0022. Ví dụ: biểu thức sau đây hợp lệ và tạo ra kết quả dự kiến:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"