- GitHub Developer / GraphQL API v4
2018-11-01:
GitHub REST API v3 だと認証なし(API 使用頻度に制限あり)、GitHub アカウントによる認証の双方で使えたけど、
GitHub GraphQL API v4 では OAuth token 必須。
カジュアルな使い方だとアカウント設定不要なので v3 のが使い易いかもしれない。
一方、REST API だとフィールドがごっそり降って来てたのが、GraphQL API だと要求したフィールドだけが降ってくるので I/O のペイロードはコンパクトになる気がする。
GitHub REST API v3 だと認証なし(API 使用頻度に制限あり)、GitHub アカウントによる認証の双方で使えたけど、
GitHub GraphQL API v4 では OAuth token 必須。
カジュアルな使い方だとアカウント設定不要なので v3 のが使い易いかもしれない。
一方、REST API だとフィールドがごっそり降って来てたのが、GraphQL API だと要求したフィールドだけが降ってくるので I/O のペイロードはコンパクトになる気がする。
認証には HTTP リクエストヘッダに以下のフィールドを突っ込む。
各 OAUTH_TOKEN に与える権限は後から変更可能だが、OAUTH_TOKEN の値は生成時の 1 回のみ閲覧可能。
紛失したら、OAUTH_TOKEN を失効(revoke)させる。
参考:
Authorization: bearer OAUTH_TOKENOAUTH_TOKEN は、GitHub にログインしてアカウントの settings にある Developer settings の Personal access tokens で生成(generate)したものを使用する。
各 OAUTH_TOKEN に与える権限は後から変更可能だが、OAUTH_TOKEN の値は生成時の 1 回のみ閲覧可能。
紛失したら、OAUTH_TOKEN を失効(revoke)させる。
参考:
- GitHub GraphQL API v4 / Guides / Forming Calls with GraphQL
POST mehtod で渡すんだけど、通常のエンコード(var1=val1&var2=val2&... 形式)じゃなくて JSON ? で "query" ってキーに GraphQL クエリ(JSON っぽい書式の DSL ?)をそのまま渡す。
ただし、query の値の中に生の改行コードが混じってると Status: 400 Bad Request になる。エスケープシーケンスで \n みたいに表現されてれば問題はないっぽいけど、どこかにドキュメントされてる?
例えば、
改行は
クエリ可能な要素数は first, last で 100 個制限。
なので、要素数の多い項目にクエリかける場合は Pagination 処理が必須。
各要素の cursor を before, after に与えると、first, last の基準位置を設定できる。
例えば、上記 ※1 の処理で、
before には先頭の要素の cursor、after には末尾の要素の cursor を食わせればよいので、以下のようになる。
REST API だと page と per_page 使ってランダムアクセス的な取得が出来ていたのに、2018-11-01 現在の GraphQL API では、少なくとも repositories を例に取ると argument で offset が使えないため、双方向リスト的にシーケンシャルなアクセスをするしかないのが面倒なところ。
参考:
ただし、query の値の中に生の改行コードが混じってると Status: 400 Bad Request になる。エスケープシーケンスで \n みたいに表現されてれば問題はないっぽいけど、どこかにドキュメントされてる?
例えば、
# ※1 wget -qSO- \ https://api.github.com/graphql \ --header="Authorization: Bearer ${OAUTH_TOKEN}" \ --post-data='{"query":"query{user(login: \"'"${LOGIN}"'\") {repositories(first:2){totalCount edges{ cursor node{url}} pageInfo{ hasPreviousPage hasNextPage } }}}"}'で、login 名が $LOGIN のユーザーのリポジトリ、先頭 2 つを挙げる。
改行は
wget -qSO- \ https://api.github.com/graphql \ --header="Authorization: Bearer ${OAUTH_TOKEN}" \ --post-data='{"query":"query{user(login: \"'"${LOGIN}"'\") {repositories(first:2){totalCount edges{ cursor node{url}} pageInfo{ hasPreviousPage hasNextPage } }}}"'$'\n''}'とか
wget -qSO- \ https://api.github.com/graphql \ --header="Authorization: Bearer ${OAUTH_TOKEN}" \ --post-data='{"query":"query{user(login: \"'"${LOGIN}"'\") {repositories(first:2){totalCount edges{ cursor node{url}}\npageInfo{ hasPreviousPage hasNextPage } }}}"'は大丈夫だけど、
wget -qSO- \ https://api.github.com/graphql \ --header="Authorization: Bearer ${OAUTH_TOKEN}" \ --post-data='{"query":"query{user(login: \"'"${USERNAME}"'\") {repositories(first:2){totalCount edges{ cursor node{url}}'$'\n''pageInfo{ hasPreviousPage hasNextPage } }}}"'だと Status: 400 Bad Request になる。
クエリ可能な要素数は first, last で 100 個制限。
なので、要素数の多い項目にクエリかける場合は Pagination 処理が必須。
各要素の cursor を before, after に与えると、first, last の基準位置を設定できる。
例えば、上記 ※1 の処理で、
{"data":{"user":{"repositories":{"totalCount":16,"edges":[{"cursor":"Y3Vyc29yOnYyOpHOANC34w==","node":{"url":"https://github.com/kou1okada/apt-cyg"}},{"cursor":"Y3Vyc29yOnYyOpHOANTakw==","node":{"url":"https://github.com/kou1okada/ruby"}}],"pageInfo":{"hasPreviousPage":false,"hasNextPage":true}}}}}が得られた場合、整形すると以下のようになるが、
{ 'data': { 'user': { 'repositories': { 'totalCount': 16, 'edges': [ { 'cursor': 'Y3Vyc29yOnYyOpHOANC34w==', 'node': { 'url': 'https://github.com/kou1okada/apt-cyg' } }, { 'cursor': 'Y3Vyc29yOnYyOpHOANTakw==', 'node': { 'url': 'https://github.com/kou1okada/ruby' } } ], 'pageInfo': { 'hasPreviousPage': false, 'hasNextPage': true } } } } }その場合、hasPreviousPage が true なら before が可能で、hasNextPage が true なら after が可能なので、
before には先頭の要素の cursor、after には末尾の要素の cursor を食わせればよいので、以下のようになる。
# before wget -qSO- \ https://api.github.com/graphql \ --header="Authorization: Bearer ${OAUTH_TOKEN}" \ --post-data='{"query":"query{user(login: \"'"${LOGIN}"'\") {repositories(first:2 before:\"'"${CURSOR}"'\"){totalCount edges{ cursor node{url}} pageInfo{ hasPreviousPage hasNextPage } }}}"}' # after wget -qSO- \ https://api.github.com/graphql \ --header="Authorization: Bearer ${OAUTH_TOKEN}" \ --post-data='{"query":"query{user(login: \"'"${LOGIN}"'\") {repositories(first:2 after:\"'"${CURSOR}"'\"){totalCount edges{ cursor node{url}} pageInfo{ hasPreviousPage hasNextPage } }}}"}'hasPreviousPage が false の場合に before、hasNextPage が false の場合に after を与えても、エラーにはならず、
{"data":{"user":{"repositories":{"totalCount":16,"edges":[],"pageInfo":{"hasPreviousPage":false,"hasNextPage":false}}}}}整形すると
{ 'data': { 'user': { 'repositories': { 'totalCount': 16, 'edges': [ ], 'pageInfo': { 'hasPreviousPage': false, 'hasNextPage': false } } } } }のように空の結果が返って来る。
REST API だと page と per_page 使ってランダムアクセス的な取得が出来ていたのに、2018-11-01 現在の GraphQL API では、少なくとも repositories を例に取ると argument で offset が使えないため、双方向リスト的にシーケンシャルなアクセスをするしかないのが面倒なところ。
参考:
- GraphQL / Pagination
- GitHub GraphQL API v4 / Object
- User # repositories
- RepositoryConnection
Personal access token への権限付与で
更に、Gist の方は gists(privacy: ALL|PUBLIC|SECRET) を適切に付与しておかないと public gist しか引っかからないのだが、
GitHub の方は repositories(privacy: PRIVATE|PUBLIC) なので、両方検索したい場合は privacy を付与しては駄目なようだ。
- ☑ security_events : Read and write security events
- ☑ gist : Create gists
更に、Gist の方は gists(privacy: ALL|PUBLIC|SECRET) を適切に付与しておかないと public gist しか引っかからないのだが、
GitHub の方は repositories(privacy: PRIVATE|PUBLIC) なので、両方検索したい場合は privacy を付与しては駄目なようだ。
タグ
コメントをかく