שליחת בקשת HTTP

אפשר להגדיר שלב בתהליך העבודה שיוצר קריאת HTTP, ולהקצות את התגובה מהקריאה למשתנה. לדוגמה, אפשר להפעיל Google Cloudשירות כמו פונקציות Cloud Run או Cloud Run באמצעות בקשת HTTP.

אל תתבלבלו בין הפעלה של שירות באמצעות בקשת HTTP לבין שימוש במחברים של Workflows כדי לבצע פעולות API. Google Cloud מחברים מפשטים את השימוש בשירותי התקשרות כי הם מטפלים בפורמט של הבקשות בשבילכם, ומספקים שיטות וארגומנטים כך שלא צריך לדעת את הפרטים של Google Cloud API.

הפעלת נקודת קצה (endpoint) של HTTP

סוג השלב הזה מאפשר לשלוח בקשת HTTP. יש תמיכה בבקשות HTTP ו-HTTPS. לשיטות הנפוצות ביותר של בקשות HTTP יש קיצור דרך לקריאה (למשל http.get ו-http.post), אבל אפשר ליצור כל סוג של בקשת HTTP על ידי הגדרת השדה call לערך http.request וציון סוג הבקשה באמצעות השדה method.

YAML

  - STEP_NAME:
      call: HTTP_REQUEST
      args:
          url: URL_VALUE
          method: REQUEST_METHOD
          private_service_name: "REGISTERED_SERVICE"
          headers:
              HEADER_KEY:HEADER_VALUE
              ...
          body:
              BODY_KEY:BODY_VALUE
              ...
          query:
              QUERY_KEY:QUERY_VALUE
              ...
          auth:
              type: AUTH_TYPE
              scope: AUTH_SCOPE
              scopes: AUTH_SCOPE
              audience: AUDIENCE
          timeout: TIMEOUT_IN_SECONDS
      result: RESULT_VALUE
    

JSON

  [
    {
      "STEP_NAME": {
        "call": "HTTP_REQUEST",
        "args": {
          "url": "URL_VALUE",
          "method": "REQUEST_METHOD",
          "private_service_name": "REGISTERED_SERVICE",
          "headers": {"HEADER_KEY":"HEADER_VALUE",
          ...
          },
          "body": {"BODY_KEY":"BODY_VALUE",
          ...
          },
          "query": {"QUERY_KEY":"QUERY_VALUE",
          ...
          },
          "auth": {
            "type":"AUTH_TYPE",
            "scope":"AUTH_SCOPE",
            "scopes":"AUTH_SCOPE",
            "audience":"AUDIENCE"
          },
          "timeout": "TIMEOUT_IN_SECONDS"
        },
        "result": "RESULT_VALUE"
      }
    }
  ]
    

מחליפים את מה שכתוב בשדות הבאים:

  • HTTP_REQUEST: חובה. משתמשים באחת מהאפשרויות הבאות לבקשות HTTP:
    • http.delete
    • http.get
    • http.patch
    • http.post
    • http.put
    • http.request
  • URL_VALUE: חובה. כתובת ה-URL שאליה נשלחת הבקשה.
  • REQUEST_METHOD: חובה אם משתמשים בסוג השיחה http.request. סוג ה-method של בקשת ה-HTTP שבה רוצים להשתמש. לדוגמה:
    • GET
    • POST
    • PATCH
    • DELETE
  • REGISTERED_SERVICE: אופציונלי. שם שירות רשום ב-Service Directory בפורמט projects/PROJECT_ID/locations/LOCATION/namespaces/NAMESPACE_NAME/services/SERVICE_NAME. מידע נוסף זמין במאמר הפעלת נקודת קצה פרטית באמצעות מרשם השירותים של Service Directory.
  • HEADER_KEY:HEADER_VALUE: אופציונלי. שדות כותרת להזנת קלט ל-API.

    אם משתמשים בכותרת Content-Type כדי לציין את סוג המדיה של גוף הבקשה, רק הסוגים הבאים נתמכים:

    • application/json או application/type+json – צריך להיות מפה
    • application/x-www-form-urlencoded – חייב להיות מחרוזת לא מקודדת
    • text/type – חייב להיות מחרוזת

    אם מציינים כותרת Content-Type, הגוף מקודד לפי ההנחיות. לדוגמה, יכול להיות שזה יהיה JSON או קידוד תווים שמתאים לכתובות URL.

    אם משתמשים בכותרת User-Agent כדי לזהות את סוכן המשתמש ששולח את הבקשה, צריך לפעול לפי ההנחיות הבאות:

    • ערך ברירת המחדל הוא GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs).
    • אם מציינים ערך, GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs) מצורף לערך הזה

      לדוגמה, אם מציינים את הערך User-Agent: "MY_USER_AGENT_VALUE", כותרת בקשת ה-HTTP תהיה כפי שמוצג בהמשך (עם רווח בין הערך שצוין לבין ברירת המחדל שנוספה):

      MY_USER_AGENT_VALUE GoogleCloudWorkflows; (+https://cloud.google.com/workflows/docs)
  • BODY_KEY:BODY_VALUE: אופציונלי. שדות הגוף שבהם צריך לספק קלט ל-API.

    אם לא מציינים כותרת Content-Type, ואם יש גוף בקשה, חלים הכללים הבאים:

    • אם ערך הגוף הוא בבייט, הכותרת מוגדרת כ-Content-Type: application/octet-stream.
    • אחרת, הגוף מקודד ב-JSON והכותרת מוגדרת ל-Content-Type: application/json; charset=utf-8.
    הדוגמה הבאה היא של מבנה גוף ששווה למטען ייעודי (payload) של JSON:

    YAML

    body:
      requests:
      - image:
          source:
            gcsImageUri: ${gsUri}
        features:
        - type: LABEL_DETECTION
        - type: SAFE_SEARCH_DETECTION
        - type: IMAGE_PROPERTIES
    result: imageAnalysisResponse

    JSON

    {
      "requests":[
        {
          "image": {
            "source": {
                "gcsUri": "img.png"
            }
          },
          "features": [
            { "type":"LABEL_DETECTION" },
            { "type":"SAFE_SEARCH_DETECTION" },
            { "type":"IMAGE_PROPERTIES" },
          ]
        }
      ]
    }
  • QUERY_KEY:QUERY_VALUE: אופציונלי. שדות שאילתה שמשמשים להזנת קלט ל-API.
  • AUTH_TYPE: אופציונלי. חובה אם ממשק ה-API שאליו מתבצעת הקריאה דורש אימות. אפשר להשתמש ב-OIDC או ב-OAuth2. מידע נוסף זמין במאמר בנושא שליחת בקשות מאומתות מתהליך עבודה.
    • AUTH_SCOPE: אופציונלי. מגבילה את הגישה של אפליקציה לחשבון של משתמש. משתמשים במקש scope או במקש scopes.

      המפתח scope תומך במחרוזת או ברשימת מחרוזות. לדוגמה:

      "https://www.googleapis.com/auth/cloud-platform"

      או

      ["https://www.googleapis.com/auth/cloud-platform", "scope2", "scope3"]

      המפתח scopes, בנוסף לתמיכה במחרוזת או ברשימה של מחרוזות, תומך במחרוזות שמופרדות בפסיקים וברווחים. לדוגמה:

      "https://www.googleapis.com/auth/cloud-platform scope2 scope3"

      או

      "https://www.googleapis.com/auth/cloud-platform,scope2,scope3"

      מידע נוסף זמין במאמר היקפי OAuth 2.0 ל-Google APIs.

    • AUDIENCE: אופציונלי. מציין את הקהל של אסימון OIDC. כברירת מחדל, הערך שמוגדר הוא אותו ערך כמו url, אבל צריך להגדיר אותו ככתובת ה-URL הבסיסית של השירות. לדוגמה: https://region-project.cloudfunctions.net/hello_world.
  • TIMEOUT_IN_SECONDS: אופציונלי. כמה שניות יכולה בקשה לפעול לפני שמוחזר חריג. הערך המקסימלי הוא 1,800 שניות.
  • RESULT_VALUE: אופציונלי. שם המשתנה שבו מאוחסנת התוצאה של שלב הפעלת HTTP.

גישה לנתוני תגובת HTTP שנשמרו במשתנה

אם הכותרת Content-Type של התגובה מציינת application/jsonסוג מדיה, תגובת ה-JSON שנשמרת במשתנה מומרת אוטומטית למפה שאפשר לגשת אליה.

במקרה הצורך, משנים את ה-API שמתבצעת אליו קריאה כדי לציין את סוג המדיה application/json בכותרת התגובה Content-Type. אחרת, אפשר להשתמש בפונקציות json.decode ו-text.encode כדי להמיר את גוף התגובה למפה. לדוגמה:

json.decode(text.encode(RESPONSE_FROM_API))

ב-Workflows יש כלי מובנה לניתוח נתונים, שמאפשר גישה לנתונים האלה. כדי לגשת לשדות מתגובת ה-HTTP, משתמשים בתחביר הבא:

${VARIABLE_NAME.body|code|headers.PATH_TO_FIELD}

מחליפים את מה שכתוב בשדות הבאים:

  • VARIABLE_NAME: השם של משתנה זרימת העבודה שבו שמרתם תגובת JSON.
  • body: משתמשים בשדה body כדי לגשת לגוף של תגובת ה-HTTP.
  • code: משתמשים בשדה code כדי לגשת לקוד התגובה של HTTP.
  • headers: משתמשים בשדה headers כדי לגשת לכותרות של תגובות ה-HTTP לפי שם.
  • PATH_TO_FIELD: הנתיב לשדה בתגובת ה-JSON שרוצים לגשת אליו. יכול להיות שזה השם של השדה, או שאם השדה מקונן בתוך אובייקט, הוא יכול להיות מהצורה object1.object2.field.

לדוגמה, אם API מחזיר {"age":50} ותהליך עבודה מאחסן את התגובה הזו במשתנה שנקרא age_response, הדוגמה הבאה מחזירה את הערך של השדה age, ובמקרה הזה, 50:

age_response.body.age

דוגמאות

בדוגמאות האלה אפשר לראות את התחביר.

הקצאת התגובה מקריאה ל-API

אלא אם תזינו מונח חיפוש משלכם, הדוגמה הזו משתמשת במיקום שלכם כדי ליצור מונח חיפוש, שאותו היא מעבירה אל Wikipedia API. Google Cloudמוחזרת רשימה של מאמרי ויקיפדיה קשורים.

YAML

main:
  params: [input]
  steps:
    - checkSearchTermInInput:
        switch:
          - condition: '${"searchTerm" in input}'
            assign:
              - searchTerm: '${input.searchTerm}'
            next: readWikipedia
    - getLocation:
        call: sys.get_env
        args:
          name: GOOGLE_CLOUD_LOCATION
        result: location
    - setFromCallResult:
        assign:
          - searchTerm: '${text.split(location, "-")[0]}'
    - readWikipedia:
        call: http.get
        args:
          url: 'https://en.wikipedia.org/w/api.php'
          query:
            action: opensearch
            search: '${searchTerm}'
        result: wikiResult
    - returnOutput:
        return: '${wikiResult.body[1]}'

JSON

{
  "main": {
    "params": [
      "input"
    ],
    "steps": [
      {
        "checkSearchTermInInput": {
          "switch": [
            {
              "condition": "${\"searchTerm\" in input}",
              "assign": [
                {
                  "searchTerm": "${input.searchTerm}"
                }
              ],
              "next": "readWikipedia"
            }
          ]
        }
      },
      {
        "getLocation": {
          "call": "sys.get_env",
          "args": {
            "name": "GOOGLE_CLOUD_LOCATION"
          },
          "result": "location"
        }
      },
      {
        "setFromCallResult": {
          "assign": [
            {
              "searchTerm": "${text.split(location, \"-\")[0]}"
            }
          ]
        }
      },
      {
        "readWikipedia": {
          "call": "http.get",
          "args": {
            "url": "https://en.wikipedia.org/w/api.php",
            "query": {
              "action": "opensearch",
              "search": "${searchTerm}"
            }
          },
          "result": "wikiResult"
        }
      },
      {
        "returnOutput": {
          "return": "${wikiResult.body[1]}"
        }
      }
    ]
  }
}

שליחת בקשת HTTP POST חיצונית

בדוגמה הזו מתבצעת בקשת POST לנקודת קצה חיצונית של HTTP.

YAML

- send_message:
    call: http.post
    args:
      url: https://www.example.com/endpoint
      body:
        some_val: "Hello World"
        another_val: 123
    result: the_message
- return_value:
    return: ${the_message.body}

JSON

[
  {
    "send_message": {
      "call": "http.post",
      "args": {
        "url": "https://www.example.com/endpoint",
        "body": {
          "some_val": "Hello World",
          "another_val": 123
        }
      },
      "result": "the_message"
    }
  },
  {
    "return_value": {
      "return": "${the_message.body}"
    }
  }
]

ביצוע בקשת HTTP GET חיצונית עם כותרות

בדוגמה הזו מבוצעת בקשת GET עם כותרת מותאמת אישית. אפשר גם לספק הגדרות של כותרות בהתאמה אישית כששולחים סוגים אחרים של בקשות HTTP.

YAML

- get_message:
    call: http.get
    args:
      url: https://www.example.com/endpoint
      headers:
        Content-Type: "text/plain"
      query:
        some_val: "Hello World"
        another_val: 123
    result: the_message
- return_value:
    return: ${the_message.body}

JSON

[
  {
    "get_message": {
      "call": "http.get",
      "args": {
        "url": "https://www.example.com/endpoint",
        "headers": {
          "Content-Type": "text/plain"
        },
        "query": {
          "some_val": "Hello World",
          "another_val": 123
        }
      },
      "result": "the_message"
    }
  },
  {
    "return_value": {
      "return": "${the_message.body}"
    }
  }
]

שימוש ב-OIDC לאימות כששולחים בקשה לפונקציות של Cloud Run

בדוגמה הזו מתבצעת בקשת HTTP באמצעות OIDC על ידי הוספת קטע auth לקטע args בהגדרת תהליך העבודה, אחרי ציון כתובת ה-URL.

YAML

- call_my_function:
    call: http.post
    args:
      url: https://us-central1-myproject123.cloudfunctions.net/myfunc1
      auth:
        type: OIDC
      body:
        some_val: "Hello World"
        another_val: 123
    result: the_message
- return_value:
    return: ${the_message.body}

JSON

[
  {
    "call_my_function": {
      "call": "http.post",
      "args": {
        "url": "https://us-central1-myproject123.cloudfunctions.net/myfunc1",
        "auth": {
          "type": "OIDC"
        },
        "body": {
          "some_val": "Hello World",
          "another_val": 123
        }
      },
      "result": "the_message"
    }
  },
  {
    "return_value": {
      "return": "${the_message.body}"
    }
  }
]

זיהוי וטיפול בשגיאות של בקשות HTTP

בדוגמה הזו מיושם handler מותאם אישית לחריגים שמבוסס על קוד הסטטוס של HTTP שמוחזר על ידי בקשת GET. תהליך העבודה מזהה חריגה פוטנציאלית ומחזיר הודעת שגיאה מוגדרת מראש. אם לא מזוהה חריגה, הביצוע של תהליך העבודה נכשל והחריגה מוצגת כפי שהוחזרה על ידי בקשת ה-GET. למידע על תגי שגיאה אחרים, אפשר לעיין במאמר בנושא שגיאות בתהליך העבודה.

YAML

# Use a custom exception handler to catch exceptions and return predefined
# error messages; if the exception isn't recognized, the workflow
# execution fails and throws the exception returned by the GET request
- read_item:
    try:
      call: http.get
      args:
        url: https://example.com/someapi
        auth:
          type: OIDC
      result: API_response
    except:
      as: e
      steps:
        - known_errors:
            switch:
              - condition: ${not("HttpError" in e.tags)}
                next: connection_problem
              - condition: ${e.code == 404}
                next: url_not_found
              - condition: ${e.code == 403}
                next: auth_problem
        - unhandled_exception:
            raise: ${e}
- url_found:
    return: ${API_response.body}
- connection_problem:
    return: "Connection problem; check URL"
- url_not_found:
    return: "Sorry, URL wasn't found"
- auth_problem:
    return: "Authentication error"

JSON

[
  {
    "read_item": {
      "try": {
        "call": "http.get",
        "args": {
          "url": "https://example.com/someapi",
          "auth": {
            "type": "OIDC"
          }
        },
        "result": "API_response"
      },
      "except": {
        "as": "e",
        "steps": [
          {
            "known_errors": {
              "switch": [
                {
                  "condition": "${not(\"HttpError\" in e.tags)}",
                  "next": "connection_problem"
                },
                {
                  "condition": "${e.code == 404}",
                  "next": "url_not_found"
                },
                {
                  "condition": "${e.code == 403}",
                  "next": "auth_problem"
                }
              ]
            }
          },
          {
            "unhandled_exception": {
              "raise": "${e}"
            }
          }
        ]
      }
    }
  },
  {
    "url_found": {
      "return": "${API_response.body}"
    }
  },
  {
    "connection_problem": {
      "return": "Connection problem; check URL"
    }
  },
  {
    "url_not_found": {
      "return": "Sorry, URL wasn't found"
    }
  },
  {
    "auth_problem": {
      "return": "Authentication error"
    }
  }
]

המאמרים הבאים