googleapi
GoogleAppsAPI

Google APIのBatch Requestの仕組みを理解する

More than 1 year has passed since last update.

2018/3/26

Discontinuing support for JSON-RPC and Global HTTP Batch Endpoints

Batch Request のエンドポイントが変わるようです。

お使いの方はブログの内容をみて対応しましょう。(2019/3/25までに)

www.googleapis.com/batch

↓↓↓
www.googleapis.com/batch/<api>/<version>.


Google APIにはBatch RequestというAPIを複数実行するための仕組みがあります。

Batch Requestを使用することでAPI発行側は実行速度の向上になります。

リクエスト数が減ることによりGoogle側の負荷も減るはずなので

基本的にデメリットはないという認識です。

複数APIを実行する際はBatch Requestを積極的に使っていきましょう。

また、BatchRequestの仕組みはメール送信やWebの添付ファイル送信でも似たような仕組みが使われています。

Google APIなんて使わないという方も知っておいて損はないかと思います。

@本記事はBatch Requestの仕組みの理解を目的にしたものです。

実際に使用する際は各種Google提供のライブラリに用意されていると思いますのでそちらを利用することをおすすめします。

https://developers.google.com/discovery/libraries


前提

アクセストークンの取得まではこちらの記事を参照してください

http://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5

本記事では以下のようにACCESS_TOKENは環境変数に入れて実行しています。

export ACCESS_TOKEN=ya29.fAIcwrExRp....


普通にAPIを発行

バッチリクエスト化する前にまず普通にAPIを実行してみます。


APIの送り方


URL

各種APIによる

Method

各種APIによる 主にGET、POST、PATCH、DELETE

Authorization Header

Authorization: Bearer {ACCESS_TOKEN}

Body

POSTやPATCHで使用 主にJSON


Drive APIを使用してファイルの一覧を取得する例

Request

curl https://www.googleapis.com/drive/v3/files -H "Authorization: Bearer $ACCESS_TOKEN" 

Response

{

"kind": "drive#fileList",
"files": [
{
"kind": "drive#file",
"id": "1q5eHxwMySsmnAGV4x831txwWVZ6DDD1CmwCP4QcRBAs",
"name": "ドキュメント001",
"mimeType": "application/vnd.google-apps.document"
},
{
"kind": "drive#file",
"id": "1xXnBefD_jDcjZ-vEb50LO7xS01-AsHgdpKioQLegHrQ",
"name": "スプレッドシート001",
"mimeType": "application/vnd.google-apps.spreadsheet"
},
{
"kind": "drive#file",
"id": "1NT8jIxP_NKbzgdJyQ4FPJTFaiAROmKZmIPq_TBS8wJY",
"name": "プレゼンテーション001",
"mimeType": "application/vnd.google-apps.presentation"
}
]
}


Batch Requestに変換

実際に複数にすると長くなってわかりづらいので1件だけのBatch Requestにします。

※1件がわかれば複数も簡単です。


Batch Requestの送り方

Batch Requestは以下のように送る必要があります。


URL

https://www.googleapis.com/batch

Method

POST

Authorization Header

Authorization: Bearer {ACCESS_TOKEN}

Content-Type Header

Content-Type: multipart/mixed; boundary=BOUNDARY

Request Body

ここにそれぞれのリクエストを記載します。詳細は後述。

Content-Typeをmultipart/mixedにして「リクエストを複数含みます」と教えてあげます。

boundaryは「それぞれのリクエストをこの文字で区切ります」という意味です。本記事では"BOUNDARY"という文字列を指定します。


Request Body

フォーマットとしては以下のとおりです。

--{BOUNDARY}

Content-Type: application/http
Content-ID: xxx

HTTP情報

--{BOUNDARY}--

HTTPリクエストを表すContent-Typeとそれぞれのリクエストに対するContent-IDを指定します。

Content-IDはなんでもいいですが被らないようにしてください。また、レスポンスを解析するときに使います。(私は主キーとなりうる値を設定することが多いです)

複数送信するHTTPのRequest情報がRequest Bodyに入る形になります。

なお、この際にAuthorizationは外します。(入れても効かなかったです)

Batch Requestに設定したAuthorizationが強制的にに適用されるみたいです。

図に表すとこんな感じになります。

Batch Request概要図.png


実際に送ってみる

Request Bodyはcurlからファイル指定で実行するためにファイルで保管しておきます。


databinary.txt

--BOUNDARY

Content-Type: application/http
Content-ID: 1

GET https://www.googleapis.com/drive/v3/files

--BOUNDARY--


Request

curl https://www.googleapis.com/batch -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: multipart/mixed; boundary=BOUNDARY" --data-binary @databinary.txt

Response

--batch_oysSsPRlgxc_AAP4j4WrTtE

Content-Type: application/http
Content-ID: response-1

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Date: Tue, 02 Feb 2016 21:40:32 GMT
Expires: Tue, 02 Feb 2016 21:40:32 GMT
Cache-Control: private, max-age=0
Content-Length: 610

{
"kind": "drive#fileList",
"files": [
{
"kind": "drive#file",
"id": "1q5eHxwMySsmnAGV4x831txwWVZ6DDD1CmwCP4QcRBAs",
"name": "ドキュメント001",
"mimeType": "application/vnd.google-apps.document"
},
{
"kind": "drive#file",
"id": "1xXnBefD_jDcjZ-vEb50LO7xS01-AsHgdpKioQLegHrQ",
"name": "スプレッドシート001",
"mimeType": "application/vnd.google-apps.spreadsheet"
},
{
"kind": "drive#file",
"id": "1NT8jIxP_NKbzgdJyQ4FPJTFaiAROmKZmIPq_TBS8wJY",
"name": "プレゼンテーション001",
"mimeType": "application/vnd.google-apps.presentation"
}
]
}

--batch_oysSsPRlgxc_AAP4j4WrTtE--

リクエストを送った時と同じようにGoogleが設定したBOUNDARYが設定されていますのでクライアント側はBOUNDARYで区切って処理していきます。

この時のContent-IDはresponse-{リクエスト時に送ったContent-ID}という形になります。

この値によりどのリクエストのレスポンスかどうかの判断が可能です。(リクエストと同じ順番で返ってくるかもしれませんがそのほうが安全だと思います)


おまけ(POSTリクエスト例)

Content-Lengthがなくても一応通るようです。

※ちなみにこのリクエストは1つ目で権限を追加して、2つ目で権限の一覧を抜いていますが、2つ目の権限一覧の結果には1つ目のリクエストで追加した権限は反映されていません。

バッチリクエストは順番を保証しないため順番をあてにしたリクエストはNGです。

--BOUNDARY

Content-Type: application/http
content-id: 1

POST /drive/v3/files/17zoAl-wCvZdtvXLyW9lnlwODU77golDR_CcLK1mrgiE/permissions
Content-Type: application/json; charset=UTF-8

{
"emailAddress": "user1@howdylikes.jp",
"role": "writer",
"type": "user"
}
--BOUNDARY
Content-Type: application/http
content-id: 2

GET /drive/v3/files/1428x4m9MSiMerQizvKXWbKhXh_a3Ye6lHhUl0HwjkEw/permissions

--BOUNDARY--


その他


リクエスト上限

APIの種別によりまちまちですのでリファレンスを参照してください。

Driveは100 https://developers.google.com/drive/v3/web/batch

Calendarは50 https://developers.google.com/google-apps/calendar/batch

Directoyは1000 https://developers.google.com/admin-sdk/directory/v1/guides/batch


注意点

すべてのAPIがBatch Request化できるわけではありません。