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

Bạn đang xem tài liệu về Apigee Edge.
Truy cập vào tài liệu Apigee X.
Thông tin

Câu lệnh điều kiện là một 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ư một 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à RouteRule. Bằng cách xác định các câu lệnh có điều kiện, bạn sẽ xác định hành vi động cho API của mình. Hành vi linh hoạt này cho phép bạn thực hiện 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 hoạt 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 các proxy API bằng cách sử dụng kết hợp điều kiệnbiến. 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 một câu lệnh có điều kiện, bạn hãy thêm một toán tử có điều kiện và một 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ể dùng ~/ hoặc MatchesPath. Bạn cũng có thể so khớp các biểu thức chính quy JavaRegex bằng toán tử ~~.

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

Biến

Các điều kiện hoạt động bằng cách đánh giá giá trị của biến. Biến là một thuộc tính của giao dịch HTTP do một proxy API thực thi hoặc một 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 sẵn một danh sách dài các biến được liên kết với những thứ như thời gian hệ thống, thông tin mạng của ứng dụng, tiêu đề HTTP trên các thông báo, cấu hình proxy API, việc thực thi chính sách, v.v. Thao tác này sẽ tạo ra một ngữ cảnh phong phú mà bạn có thể dùng để thiết lập các câu lệnh có điều kiện.

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

Hãy tưởng tượng rằng bạn cần tạo một câu lệnh có điều kiện sẽ chỉ thực thi một chính sách khi thông báo yêu cầu là GET. Để tạo một điều kiện đá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 bên dưới. 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 câu lệnh như vậy để đánh giá các điều kiện. Ví dụ trên sẽ đánh giá là true nếu động từ HTTP được 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ẽ đánh giá là sai.

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

Khi đính kèm một điều kiện vào một Luồng, bạn sẽ tạo ra 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à đúng. Bạn có thể đính kèm bao nhiêu Chính sách tuỳ ý 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 ra các quy tắc xử lý chuyên biệt cao cho 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à GET:

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

Cách tạo một Flow cho GET và một Flow 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 chính Bước trong chính sách. Điều kiện sau đây khiến Chính sách VerifyApiKey chỉ được thực thi nếu thông báo yêu cầu là 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ào các Luồng đó, cho phép một proxy API thực thi một bộ chính sách cho các yêu cầu GET và một bộ chính sách khác cho các yêu cầu POST.

Để biết thông tin tham khảo toàn diện, 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 duy nhất có tên là Convert-for-devices, được định cấu hình trong luồng phản hồi ProxyEndpoint. Thêm Điều kiện làm phần tử vào thực thể mà điều kiện áp dụng. Trong ví dụ này, điều kiện là một thành phần của quy trình. Do đó, quy trình sẽ thực thi bất cứ khi nào câu lệnh đánh giá là true.

<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 sẽ lưu trữ các giá trị của tất cả tiêu đề HTTP hiện có dưới dạng các biến. Nếu yêu cầu chứa một 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.

Với 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ó đánh giá là true 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ì Flow có điều kiện sẽ thực thi và chính sách XMLtoJSON có tên ConvertToJSON sẽ được thực thi. Nếu không, Flow sẽ không được thực thi và phản hồi XML sẽ được trả về mà không bị sửa đổi (ở định dạng XML) cho ứng dụng yêu cầu.

Ví dụ 2

Hãy sử 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 sang 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 có định dạng XML từ Weather API 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 hướng dẫn proxy API lấy thông báo phản hồi, thực hiện chuyển đổi từ XML sang JSON bằng 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 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 một 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ả các phản hồi từ XML sang JSON trước khi chúng được trả về cho ứng dụng khách, 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 tiêu chuẩn, phản hồi sẽ được định dạng ở dạng 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 máy khách yêu cầu là thiết bị di động. Để bật hành vi động như vậy, bạn phải thêm một câu lệnh có điều kiện vào Flow.

Kiểm thử quy trình có điều kiện

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

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

hoặc để in đẹp ở nơi có Python:

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

Phản hồ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 mà 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 ở định dạng XML.

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

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

Phản hồ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ó điều kiện trong một luồng 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:

Liên kết

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

Tóm tắt: Toán tử "Trùng khớp" mang đến cho bạn 2 khả năng. Bạn có thể khớp chuỗi theo nghĩa đen hoặc khớp ký tự đại diện bằng "*". Như bạn có thể dự đoán, ký tự đại diện sẽ khớp với 0 hoặc nhiều ký tự. Hãy cùng xem cách hoạt động của tính năng này.

Tệp XML sau đây cho thấy một điều kiện Bước. Thao tác này sẽ thực thi chính sách SomePolicy khi điều kiện đánh giá là true. Trong ví dụ này, chúng ta sẽ kiểm thử biến proxy.pathsuffix, một biến tích hợp trong Edge lưu trữ hậu tố đường dẫn của yêu cầu. Tuy nhiên, bạn có thể kiểm thử giá trị của bất kỳ biến luồng nào chứa một 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 là chuỗi ký tự "/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ố đường dẫn proxy khớp chính xác với "/cat". Thao tác này sẽ không thực thi nếu hậu tố là /bat hoặc /dog hoặc "/" hoặc bất kỳ hậu tố nào khác.

Bây giờ, hãy xem xét câu lệnh có điều kiện này, trong đó 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 mọi ký tự và "/cat" là một kết quả 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 mọi ký tự, "/bat" là một 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 các chữ cái "wl" 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 0 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" sẽ tạo ra một 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" sẽ tạo ra một kết quả khớp. Lưu ý cách một biểu thức như thế này có thể khiến bạn gặp rắc rối vì nó khớp với mọi thứ sau các ký tự theo nghĩa đen!

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

Có. Giả sử bạn có một điều kiện 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 khỏi các ký tự bằng toán tử Matches?

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ử Khớp đang tìm kiếm chuỗi ký tự "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 bất thường, nhưng vẫn khớp.

JavaRegex

Như bạn có thể thấy, toán tử "Matches" (Khớp) rất phù hợp với những trường hợp đơn giản. Nhưng bạn có thể sử dụng một toán tử khác, đó là toán tử "JavaRegex" hoặc "~~". Hai toán tử này giống nhau, 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 trong ngôn ngữ Java. Cách hoạt động của toán tử JavaRegex rất khác với toán tử Matches, vì vậy, bạn cần lưu ý để không nhầm lẫn giữa 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âu lệnh có điều kiện.

Đoạn mã sau đây cho thấy một điều kiện Bước. Thao tác này sẽ thực thi chính sách SomePolicy nếu điều kiện đánh giá là true. Trong ví dụ này, chúng ta sẽ kiểm thử biến proxy.pathsuffix, một biến tích hợp 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ố đường dẫn là chuỗi chữ "/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ư toán tử Matches, trong trường hợp này 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ố đường dẫn proxy khớp chính xác với "/cat". Thao tác này sẽ không thực thi nếu hậu tố là /bat hoặc /dog hoặc bất kỳ hậu tố nào khác.

Bây giờ, hãy tạo một biểu thức chính quy bằng cách sử dụ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! Bộ định lượng "*" khớp với 0 hoặc nhiều ký tự trướ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 "?". Bộ định lượng này khớp với ký tự trước đó một lần hoặc không khớp lần nào.

<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 1 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" nên điều kiện có giá trị là true.

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. Định lượng từ "?" khớp với một trong số các ký tự trước đó, đó là "a".

Tiếp theo, chúng ta sẽ sử dụng kiểu biểu thức chính quy "[abc]" hoặc "nhóm". Nó khớp với các ký tự "a" hoặc "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ó. Ở đây, chúng ta đang sử dụng biểu thức chính quy và biểu thức "[cbr]" khớp với "c", "b" HOẶC "r". Những cuộc gọi này cũng là kết quả 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à một kết quả khớ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ó một điều kiện 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 này khớp với 0 hoặc 1 ký tự đứng 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: "~/". Toán tử này trông hơi giống toán tử Matches (~) và JavaRegex (~~). Nhưng MatchesPath lại hoàn toàn khác.

Hãy nhớ rằng toán tử này xem xét một đường dẫn như 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 này 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à hai dấu hoa thị (**). Dấu hoa thị đơn 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 ví dụ. Trong ví dụ này, chúng ta sẽ kiểm thử biến proxy.pathsuffix, đây là một biến tích hợp trong Edge lưu trữ hậu tố đường dẫn của yêu cầu. Tuy nhiên, 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 một 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ởi "/*".

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 phần tử đường dẫn khác (phần sau "/animals/"), nhưng phần tử đó 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 có một phần tử ("/cats") xuất hiện 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ì dấu hoa thị đơn 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".

Bây 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 bạn phải chỉ định ít nhất một phần tử đường dẫn sau đây 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 phần tử đường dẫn khác (phần sau "/animals/"), nhưng phần tử đó 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 có ít nhất một phần tử xuất hiện sau "/animals"

Lệnh gọi API:

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

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

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

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

Bạn có thể kết hợp dấu hoa thị đơn (*) và dấu hoa thị kép (**) để tinh chỉnh thêm tính năng 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 một 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

Các dịch vụ RESTful là tập hợp các tài nguyên API. Tài nguyên API là một đoạn đường dẫn URI 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à dự báo thời tiết, thì dịch vụ phụ trợ của bạn có thể xác định hai tài nguyên API:

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

Khi tạo một proxy API (như minh hoạ trong phần Tạo proxy API đầu tiên), ít nhất bạn cũng đang tạo một URL cơ sở bí danh ánh xạ đến dịch vụ phụ trợ của mình. 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 các lệnh gọi API đến phần phụ trợ bằng cách sử dụng URL cơ sở. Nhưng khi bạn sử dụng URL của proxy API, mọi thứ sẽ trở nên thú vị.

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

Hình ảnh sau đây cho thấy sự khác biệt về hành vi giữa hai 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 không qua proxy, còn lại là một proxy Edge API có một luồng có điều kiện đến cùng một tài nguyên phụ trợ. Chúng ta 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 liên kết với các tài nguyên phụ trợ cụ thể

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

Giả sử bạn muốn Edge "làm gì đó" khi các cuộc gọi đến tài nguyên /reports hoặc /forecasts. Tại thời điểm này, bạn không cho Edge biết phải làm gì, mà chỉ cho biết rằng Edge nên lắng nghe các lệnh gọi đến những tài nguyên đó. Bạn thực hiện việc này bằng 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. Để minh hoạ khái niệm, tệp XML của proxy API sau đây cho biết những điều kiện đó có thể trông như thế nào.

<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 đó cho biết: "Khi một yêu cầu GET đến cùng với /reports/forecasts trong URL, Edge sẽ làm bất cứ điều gì bạn (nhà phát triển API) yêu cầu, thông qua các chính sách mà bạn đính kèm vào những luồng đó.

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

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

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

Bạn sẽ có thể:

  • Áp dụng hoạt động quản lý theo cách phản ánh ngữ nghĩa của mô hình API
  • Áp dụng các chính sách và hành vi theo kịch bản cho từng đường dẫn tài nguyên (URI)
  • Thu thập các 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 tài nguyên /developers đến /apps của phần phụ trợ.

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

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

Trong cửa sổ "New Conditional Flow" (Luồng có điều kiện mới), bạn sẽ nhập các cấu hình chính sau:

  • Tên quy trình công việc: 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 một lệnh gọi được gửi đến proxy có /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 thiết lập những mục 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 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 đến proxy có /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 quy trình 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, các tài nguyên API chỉ đơn giản là các luồng có điều kiện đá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 theo sau BasePath được đị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 Flow có điều kiện trong proxy API. (Xem phần Định cấu hình luồng.)

Sau khi bạn triển khai API proxy vào môi trường thử nghiệm, yêu cầu sau đây:

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

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

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

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

Để biết thêm về loại điều kiện này, hãy xem bài viết Cách so khớp bất kể ... trong Cộng đồng Apigee.

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

Trong một số trường hợp, bạn sẽ có các tài nguyên API theo hệ thống 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ả ứ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à một mã nhận dạng duy nhất được tạo cho mỗi thực thể trong một bộ sưu tập, đôi khi được chú thích như sau:

/genus/:id/species

Đường dẫn này áp dụng cho cả hai URI sau:

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

Để biểu thị cấu trúc này trong một 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 có hệ 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 đoạn URI nhất định. Để làm như vậy, hãy sử dụng ký tự đại diện dấu hoa thị kép 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à cách điều kiện luồng có điều kiện sẽ xuất hiện trong đị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ào 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 đính kèm vào 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

Sau đây là một số ví dụ về các toán tử được 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

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

Các nhà phát triển Edge thường muốn xử lý cả hai hậu tố đường dẫn này: "/cat" và "/cat/". Điều này là do một số người dùng hoặc máy khách có thể gọi API của bạn bằng dấu gạch chéo bổ sung ở cuối đường dẫn và bạn cần có thể xử lý điều đó 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. Ảnh chụp rõ ràng và dễ đọc.

Bạn có thể làm điều tương tự với Regex, nhưng theo cách 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ó. Xin 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 1 ký tự trước đó. Do đó, cả "/cat" và "/cat/" đều là kết quả 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à không được phép có ký tự nào khác.

Khớp các chuỗi tuỳ ý bằng JavaRegex

Trong tất cả các ví dụ trong chủ đề này, chúng tôi trình bày cách so khớp một trong các biến luồng tích hợp: 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ỳ chuỗi hoặc biến luồng tuỳ ý nào, cho dù đó có phải là biến luồng tích hợp như proxy.pathsuffix hay không.

Ví dụ: nếu có một điều kiện kiểm thử một chuỗi bất kỳ, 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ừ một hoạt động tra cứu máy chủ xác thực, bạn có thể sử dụng các toán tử so khớp để kiểm thử 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 chủ đề là "abc" và biểu thức chính quy là "[a-z]", thì sẽ 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ự chữ cái. Biểu thức "[a-z]+" hoạt động, cũng 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ề một danh sách vai trò dưới dạng chuỗi phân tách bằng dấu phẩy: "editor, author, 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ì "editor" 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 thức này hoạt động vì có tính đến dấu 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 tra "editor" bằng toán tử Matches:

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

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

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

Cú pháp Condition yêu cầu 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 Regex chứa dấu ngoặc kép, bạn cần một cách khác để so khớp 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, chẳng hạn 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ó 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 trong Unicode, \u0022. Ví dụ: biểu thức sau đây là hợp lệ và cho ra kết quả như mong đợi:
request.header.Content-Type ~~ "(multipart\/related)(; *type=\u0022application\/xop\+xml\u0022)"