2018/3/26
Discontinuing support for JSON-RPC and Global HTTP Batch Endpoints
Theo thông tin trên thì endpoint của Batch Request sẽ thay đổi. Những ai đang dùng thì hãy lưu ý nội dung dưới đây (cho đến 2019/3/25).
1 2 3 4 | www.googleapis.com/batch ↓↓↓ www.googleapis.com/batch/<api>/<version>. |
Trong Google API có 1 cấu trúc cho phép thực hiện nhiều API gọi là Batch Request.
Dùng Batch Request sẽ nâng cao tốc độ thực hiện của bên cung cấp API.
Mà khi số request giảm đi thì chịu tải bên Google cũng chắc chắn giảm nên cơ bản cấu trúc này không có điểm trừ nào.
Khi phải thực hiện nhiều API thì hãy tận dụng triệt để Batch Request!
Ngoài ra cơ cấu của BatchRequest cũng giống với việc bắn mail hay gửi các attach file của Web.
@Bài viết này nhằm giúp các bạn hiểu về cơ cấu của Batch Request.
Khi dùng nó trên thực tế thì nó cũng được có sẵn trong các library của các loại Google cung cấp do vậy tôi cũng recommend.
https://developers.google.com/discovery/libraries
Tiền định
Về việc get access token thì hãy tham khảo bài viết này.
http://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5
Trong bài viết này thì ACCESS_TOKEN sẽ được cho vào biến môi trường như sau.
1 2 | export ACCESS_TOKEN=ya29.fAIcwrExRp.... |
Phát hành API như bình thường
Trước khi BatchRequest hóa thì sẽ thử thực hiện API như bình thường.
Cách gửi API
<dl>
<dt>URL</dt>
<dd>dựa vào các kiểu API</dd>
<dt>Method</dt>
<dd>dựa vào các kiểu API, chủ yếu là 主にGET、POST、PATCH、DELETE</dd>
<dt>Authorization Header</dt>
<dd>Authorization: Bearer {ACCESS_TOKEN}</dd>
<dt>Body</dt>
<dd>Sử dụng ở POST và PATCH, chủ yếu là JSON</dd>
</dl>
Ví dụ dùng Drive API để get list
Request
1 2 | curl https://www.googleapis.com/drive/v3/files -H "Authorization: Bearer $ACCESS_TOKEN" |
Response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token punctuation">{</span> <span class="token property">"kind"</span><span class="token operator">:</span> <span class="token string">"drive#fileList"</span><span class="token punctuation">,</span> <span class="token property">"files"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"kind"</span><span class="token operator">:</span> <span class="token string">"drive#file"</span><span class="token punctuation">,</span> <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"1q5eHxwMySsmnAGV4x831txwWVZ6DDD1CmwCP4QcRBAs"</span><span class="token punctuation">,</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Document 001"</span><span class="token punctuation">,</span> <span class="token property">"mimeType"</span><span class="token operator">:</span> <span class="token string">"application/vnd.google-apps.document"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">"kind"</span><span class="token operator">:</span> <span class="token string">"drive#file"</span><span class="token punctuation">,</span> <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"1xXnBefD_jDcjZ-vEb50LO7xS01-AsHgdpKioQLegHrQ"</span><span class="token punctuation">,</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Spreadsheet 001"</span><span class="token punctuation">,</span> <span class="token property">"mimeType"</span><span class="token operator">:</span> <span class="token string">"application/vnd.google-apps.spreadsheet"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">"kind"</span><span class="token operator">:</span> <span class="token string">"drive#file"</span><span class="token punctuation">,</span> <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"1NT8jIxP_NKbzgdJyQ4FPJTFaiAROmKZmIPq_TBS8wJY"</span><span class="token punctuation">,</span> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Presentation 001"</span><span class="token punctuation">,</span> <span class="token property">"mimeType"</span><span class="token operator">:</span> <span class="token string">"application/vnd.google-apps.presentation"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> |
Đổi sang Batch Request
Nếu đổi nhiều thì sẽ rất dài, khó hiểu nên tôi sẽ chỉ làm 1 cái BatchRequest.
※Hiểu được 1 cái rồi thì làm nhiều cũng đơn giản thôi.
Cách gửi Batch Request
Cần gửi Batch Request như sau:
<dl>
<dt>URL</dt>
<dd>https://www.googleapis.com/batch</dd>
<dt>Method</dt>
<dd>POST</dd>
<dt>Authorization Header</dt>
<dd>Authorization: Bearer {ACCESS_TOKEN}</dd>
<dt>Content-Type Header</dt>
<dd>Content-Type: multipart/mixed; boundary=BOUNDARY</dd>
<dt>Request Body</dt>
<dd>Ghi từng request ở đây. Detail ghi sau.</dd>
</dl>
Các bạn để Content-Type thành multipart/mixed đi, tôi sẽ cho bạn biết “chứa nhiều request”.
boundary có vai trò ngăn cách mỗi request. Trong bài viết này sẽ chỉ định string “BOUNDARY”.
Request Body
Format như sau:
1 2 3 4 5 6 7 8 | --{BOUNDARY} Content-Type: application/http Content-ID: xxx Thông tin HTTP --{BOUNDARY}-- |
Chỉ định Content-ID đối với Content-Type biểu thị HTTP request và mỗi request tương ứng đó.
Content-ID thì thế nào cũng được chỉ cần không để nó trùng lặp nhau. Ngoài ra sẽ dùng khi giải thích response.
Thông tin Request của HTTP mà gửi tin nhiều lần sẽ được để trong Request Body.
Khi này thì sẽ loại bỏ Authorization (dù có để lại thì cũng không có tác dụng gì).
Hình như là các Authorization đã set trong Batch Request sẽ bị cưỡng chế apply.
Như trong hình
Try to send
Request Body sẽ lưu ở file để thực hiện chỉ định file từ curl.
1 2 3 4 5 6 7 8 | --BOUNDARY Content-Type: application/http Content-ID: 1 GET https://www.googleapis.com/drive/v3/files --BOUNDARY-- |
Request
1 2 | curl https://www.googleapis.com/batch -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: multipart/mixed; boundary=BOUNDARY" --data-binary @databinary.txt |
Response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | --batch_oysSsPRlgxc_AAP4j4WrTtE <span class="token header-name keyword">Content-Type:</span> application/http <span class="token header-name keyword">Content-ID:</span> response-1 <span class="token response-status">HTTP/1.1 <span class="token property">200 OK</span></span> <span class="token header-name keyword">Content-Type:</span> application/json; charset=UTF-8 <span class="token header-name keyword">Date:</span> Tue, 02 Feb 2016 21:40:32 GMT <span class="token header-name keyword">Expires:</span> Tue, 02 Feb 2016 21:40:32 GMT <span class="token header-name keyword">Cache-Control:</span> private, max-age=0 <span class="token header-name keyword">Content-Length:</span> 610<span class="token application/json"> <span class="token punctuation">{</span> <span class="token string">"kind"</span><span class="token punctuation">:</span> <span class="token string">"drive#fileList"</span><span class="token punctuation">,</span> <span class="token string">"files"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token string">"kind"</span><span class="token punctuation">:</span> <span class="token string">"drive#file"</span><span class="token punctuation">,</span> <span class="token string">"id"</span><span class="token punctuation">:</span> <span class="token string">"1q5eHxwMySsmnAGV4x831txwWVZ6DDD1CmwCP4QcRBAs"</span><span class="token punctuation">,</span> <span class="token string">"name"</span><span class="token punctuation">:</span> <span class="token string">"Document 001"</span><span class="token punctuation">,</span> <span class="token string">"mimeType"</span><span class="token punctuation">:</span> <span class="token string">"application/vnd.google-apps.document"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">"kind"</span><span class="token punctuation">:</span> <span class="token string">"drive#file"</span><span class="token punctuation">,</span> <span class="token string">"id"</span><span class="token punctuation">:</span> <span class="token string">"1xXnBefD_jDcjZ-vEb50LO7xS01-AsHgdpKioQLegHrQ"</span><span class="token punctuation">,</span> <span class="token string">"name"</span><span class="token punctuation">:</span> <span class="token string">"Spread sheet 001"</span><span class="token punctuation">,</span> <span class="token string">"mimeType"</span><span class="token punctuation">:</span> <span class="token string">"application/vnd.google-apps.spreadsheet"</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">"kind"</span><span class="token punctuation">:</span> <span class="token string">"drive#file"</span><span class="token punctuation">,</span> <span class="token string">"id"</span><span class="token punctuation">:</span> <span class="token string">"1NT8jIxP_NKbzgdJyQ4FPJTFaiAROmKZmIPq_TBS8wJY"</span><span class="token punctuation">,</span> <span class="token string">"name"</span><span class="token punctuation">:</span> <span class="token string">"Presentation 001"</span><span class="token punctuation">,</span> <span class="token string">"mimeType"</span><span class="token punctuation">:</span> <span class="token string">"application/vnd.google-apps.presentation"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token operator">--</span>batch_oysSsPRlgxc_AAP4j4WrTtE<span class="token operator">--</span> </span> |
Giống như khi gửi request, BOUNDARY mà Google set cũng sẽ được set nên bên client sẽ phân cách bằng BOUNDARY và xử lý.
Content-ID khi này sẽ có dạng response-{Content-ID đã gửi khi request}
.
Với giá trị này có thể nhận xem request nào sẽ response. (có thể sẽ trả về số number giống với request mà tôi nghĩ nên là như vậy thì an toàn hơn)
Mở rộng(bên POST request)
Dù không có Content-Length thì nó vẫn chạy được bình thường.
※Nhân đây thì request này, nếu thêm quyền hạn ở cái thứ nhất thì nó sẽ lược bỏ list của quyền hạn ở cái thứ 2, quyền đã thêm từ request đầu sẽ không được thể hiện trong kết quả của list quyền hạn cái thứ 2.
BatchRequest không đảm bảo thứ tự cho nên với những request yêu cầu thứ tự thì sẽ NG.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | --BOUNDARY Content-Type: application/http content-id: 1 POST /drive/v3/files/17zoAl-wCvZdtvXLyW9lnlwODU77golDR_CcLK1mrgiE/permissions Content-Type: application/json; charset=UTF-8 { "emailAddress": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__">[email protected]</a>", "role": "writer", "type": "user" } --BOUNDARY Content-Type: application/http content-id: 2 GET /drive/v3/files/1428x4m9MSiMerQizvKXWbKhXh_a3Ye6lHhUl0HwjkEw/permissions --BOUNDARY-- |
Others
GIới hạn request
Mỗi loại API thì cũng rất đa dạng nên hãy tham khảo thêm các nguồn sau.
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
Lưu ý
Không phải tất cả các API đều có thể Batch Request hóa.