HTTPリクエストを送信する
この記事では、AUTOROのHTTPRequestアクションについて紹介します。
主に以下2つのケースで使用します。
・AUTOROのコネクションに存在していない外部サービスのAPIを利用する場合
・Chrome DevToolsのNetworkタブの情報を操作したい場合
HTTPRequestアクションとは
Webサイトを閲覧したり、SNSなどに何か情報を投稿したりする場合、手元にあるコンピュータは、インターネット回線を介してサーバとなっているコンピュータに「要求(request)」を送信しています。
Webサイト上で発生しているこのような要求を、HTTPリクエストと言います。
参考:HTTPリクエストとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
これらのリクエストは、通常はWebサイト上でのクリック操作などによって自動的に送信されています。
しかし、場合によっては詳細かつ具体的な要求文書をハンドメイドで作成し、Webサーバに送信する必要があります。例えば、AUTOROのコネクションに存在していない外部サービスのAPIを利用する場合などです。
このような場合に、AUTOROのHTTPリクエストアクションを使用します。

※リクエストボディーやエンドポイントのURL等についての詳細は
各サービスが公開しているAPIドキュメントを参照して設定してください。
ワークフローの設定例(GET)
サンプルとして、Googleの書籍検索APIから書籍情報を取得するHTTPRequestを設定してみます。
今回は、Google書籍検索APIに対して、以下の要求をします。
書名に"遠野物語"が含まれる本を、1冊だけ取得する
HTTPRequestの送信先を、エンドポイントと言います。これはURLとなります。
今回はGoogleの書籍検索APIのURLを入力します。
https://www.googleapis.com/books/v1/volumes

今回はの目的は、Webサーバ(Google書籍検索API)から書籍情報を「取得」することです。
よって、リクエストメソッドにはGETを指定します。

リクエストの具体的な内容を、リクエストボディと言います。
今回は以下の内容でボディを作成していきます。
- 書籍タイトル
- 取得上限件数
今回のリクエスト内容からすると、「遠野物語」という文字をリクエストボディに含ませる必要があることが推測できます。
しかし、「遠野物語」が、著者名等ではなく「書籍タイトル」としての指定であることをコンピュータに分からせるためには、所定の形式で「遠野物語」と書く必要があります。
ここでいう、「所定の形式」は、Google書籍検索APIの公式ドキュメントから確認できます。
https://developers.google.com/books/docs/v1/using#WorkingVolumes
https://developers.google.com/books/docs/v1/using#query-params
APIドキュメントに従うと、書籍タイトル指定は「パラメータqの中で”intitle:書籍タイトル”とする」必要があるようです。
これはURIによる指定が可能なようです(※後述)。
しかし、ここではHTTPRequestアクションのリクエストボディパラメータを指定する例を示すため、一旦URIは使わない方針で行きます。
URIを使わずに、リクエストボディの標準的な記述方法であるオブジェクト形式を採用すると、以下のボディが記述できます。
{"q":"intitle:遠野物語"}
早速、リクエストボディに入力してみます。

3-1のままで実行すると、取得上限件数のデフォルトが10件であるために、最大10件の書籍が取得されてしまいます。(上限件数もAPIドキュメントに書いてあります)
APIドキュメントによれば、取得上限を1件にするためにはmaxResultsパラメータを指定する必要があるようです。
よって、3-1のオブジェクトに以下のパラメータを追加する形で対応します。
{"q":"intitle:遠野物語", "maxResults" : "1"}

ワークフローを実行してみます。結果は以下の通りです。
Google書籍検索APIのドキュメントに正確に従えば、今回のリクエストはHTTPRequestのエンドポイントURLを以下とするだけで実現できることがわかります。
https://www.googleapis.com/books/v1/volumes?q=intitle:遠野物語&maxResults=3
HTTPRequestアクションのURLを、上記URLをエンコードしたもの(※後述)に置換し、アクション内のリクエストボディ入力欄を削除するだけで、上記3-1,3-2のようなボディ指定時と同様の結果を得られます。

※URLエンコード…URLに直接アクセスしたあとにURLをコピーすると、エンコード済みのURLがクリップボードにコピーされています。

# HTTPリクエスト
+h_t_t_p_request_1:
action>: HTTPRequest
url: 'https://www.googleapis.com/books/v1/volumes'
params:
q: 'intitle:遠野物語'
maxResults: 1
method: GET
headers: ''
multipart: false
GET以外の設定例
GET以外の設定例を以下より紹介します。クリックで展開します。
POSTリクエストは、情報の登録要求を意味します。
例えば、SNSの新規投稿ボタンを押した場合、裏ではPOSTリクエストがWebサーバに送信されています。
ここでは、Chatworkに期限付きタスクを登録する例を紹介します。
参考:チャットにタスクを追加する(Chatwork公式APIドキュメント)
# 変数に保存 ルームID(チャットルームURLの#!ridから右の数字です)
+store_value_3:
action>: StoreValue
key: roomId
value: 'ルームID'
# 変数に保存 タスク名
+store_value_1:
action>: StoreValue
key: taskName
value: '適当なタスク名'
# 変数に保存 アカウントID(複数の場合、カンマ区切りで入力ください)
+store_value_2:
action>: StoreValue
key: acID
value: 'xxx,yyy,zzz'
# 変数に保存 APIトークン
+store_value_4:
action>: StoreValue
key: TOKEN
value: 'APIトークン'
# 日時を取得(任意の日時,timezoneはUTCとして下さい)
+get_time_1:
action>: GetTime
format: 'YYYY-MM-DD HH:mm'
timezone: UTC
relativeTime:
number: 2
unit: day
preposition: after
startEndOption: ''
# 変数に保存
+store_value_5:
action>: StoreValue
key: limitTime
value: +get_time_1
# HTTPリクエスト_チャットワークにタスクを追加(期限付き)
+h_t_t_p_request_1:
action>: HTTPRequest
url: 'https://api.chatwork.com/v2/rooms/${roomId}/tasks?body=${encodeURIComponent(taskName)}&limit=${moment(limitTime).utcOffset(540).unix()}&limit_type=time&to_ids=${acID}'
params: ''
method: POST
headers:
X-ChatWorkToken: ${TOKEN}
multipart: false
マルチパートをtrueにすると、ファイルを含むリクエストが可能になります。
以下は、Gyazoに画像をアップロードする例です。
# ブラウザを開く
+open_browser_1:
action>: OpenBrowser
url: 'https://www.mofa.go.jp/mofaj/area/turkmenistan/index.html'
lang: 'ja-JP'
headless: true
useShadowDomSelector: false
# スクリーンショットを撮る
+take_screenshot_1:
action>: TakeScreenshot
browser: +open_browser_1
full_page: false
type: png
# HTTPリクエスト_GayzoAPI
+h_t_t_p_request_1:
action>: HTTPRequest
url: 'https://upload.gyazo.com/api/upload'
params:
access_token: 'ここにアクセストークンを設定'
method: POST
headers:
Content-Type: 'multipart/form-data'
multipart: true
upload_file_key: imagedata
file_input_name: +take_screenshot_1
PUTでは、情報の上書き更新が可能です。
例えば、既存のブログ記事を編集後に変更を確定した場合、裏ではPUTメソッドが動いています。(※PATCHの場合もあります。)
以下記事でサンプルを紹介しています。
PATCHでは、ある情報の一部分のみを更新できます。
PUTと似たような内容となりますが、どのような挙動をするかはHTTPRequestの送信先(endpoint)次第で変わります。送信先のAPIドキュメント等から、仕様をご確認ください。
以下は、AirTableのレコードを更新するサンプルです。
※AirTableの公式APIドキュメントは、AirTableへログイン後に閲覧できます。
# HTTPリクエスト_AirTable
+h_t_t_p_request_1:
action>: HTTPRequest
url: 'https://api.airtable.com/v0/テーブルID/テーブル名/レコードID'
params: ${JSON.stringify(ここにフィールド情報などが入った変数の名前)}
method: PATCH
headers:
Authorization: 'APIトークン'
Content-Type: 'application/json'
multipart: false
DELETEはその名の通り、削除要求です。
例えば、記事の削除を確定するボタンを押した場合、裏ではDELETE要求が送信されています。
以下記事の下部にて、実行中のAUTOROセッションをHTTPリクエストによってキャンセルする例を紹介しています。
※慎重にご使用ください。
InjectScriptでHTTPRequestを送信する
HTTPRequestは、InjectScript(ページ内でスクリプトを実行)アクションを使用して送信することも可能です。
JavaScriptのXMLHttpRequestまたはfetchを使用します。
以下に例を紹介します。
以下記法でXMLHttpRequestのレスポンス(エラー含む)が取得できます。
# ブラウザを開く
+open_browser_1:
action>: OpenBrowser
url: 'https://autoro.io/'
lang: 'ja-JP'
headless: true
useShadowDomSelector: false
# ページ内でJavaScriptを実行する_XMLHTTPRequest
+inject_script_1:
action>: InjectScript
browser: +open_browser_1
code: "(async () => {\n const xmlPromise = new Promise((resolve, reject) => {\n const endpoint =\n \"https://www.googleapis.com/books/v1/volumes?q=intitle:遠野物語&maxResults=1\"; //ここにURL\n\n const xhr = new XMLHttpRequest();\n xhr.open(\"GET\", endpoint, true);\n xhr.addEventListener(\"load\", e => resolve(JSON.parse(xhr.response)));\n xhr.send();\n });\n\n return await xmlPromise.catch(error => error);\n})();\n"
returnValue: true
# ブラウザを開く
+open_browser_1:
action>: OpenBrowser
url: 'https://autoro.io/'
lang: 'ja-JP'
headless: true
useShadowDomSelector: false
# ページ内でJavaScriptを実行する_fetch
+inject_script_1:
action>: InjectScript
browser: +open_browser_1
code: "(async () => {\n const endpoint =\n \"https://www.googleapis.com/books/v1/volumes?q=intitle:遠野物語&maxResults=3\";\n\n const options = {\n method: \"GET\", // *GET, POST, PUT, DELETE, etc.\n // mode: 'cors', // no-cors, *cors, same-origin\n cache: \"no-cache\", // *default, no-cache, reload, force-cache, only-if-cached\n // credentials: 'same-origin', // include, *same-origin, omit\n headers: {\n \"Content-Type\": \"application/json\"\n // 'Content-Type': 'application/x-www-form-urlencoded',\n }\n };\n\n const resp = await fetch(endpoint, options).catch(e => e.message);\n return await resp.json().catch(e => e.message);\n})();\n"
returnValue: true
HTTPRequestアクションと同じ結果が取得されます。(※XMLHttpRequestとfetchの両方で同じ結果が得られます)
