日常的なユースケースに取り組みながら、APIの中心的な概念を見ていきましょう。
概要
ほとんどのアプリケーションは、任意の言語において既存のラッパーライブラリを使用しています。ただ、まずは基底となっているAPI HTTPメソッドについて知ることが大切です。
There's no easier way to kick the tires than through cURL.
Hello World
まずはセットアップをテストすることから始めましょう。 コマンドプロンプトを開き、次のコマンドを入力します。
$ curl https://api.github.com/zen
> Keep it logically awesome.
レスポンスは、私たちの設計思想からランダムに選択されます。
次に、Chris WanstrathのGitHubプロフィールをGET
します。
# GET /users/defunkt
$ curl https://api.github.com/users/defunkt
> {
> "login": "defunkt",
> "id": 2,
> "url": "http(s)://[hostname]/api/v3/users/defunkt",
> "html_url": "https://github.com/defunkt",
> ...
> }
うーん、JSONっぽいですね。 -i
フラグを追加して、ヘッダを入れてみましょう。
$ curl -i https://api.github.com/users/defunkt
> HTTP/1.1 200 OK
> Server: GitHub.com
> Date: Sun, 11 Nov 2012 18:43:28 GMT
> Content-Type: application/json; charset=utf-8
> Status: 200 OK
> ETag: "bfd85cbf23ac0b0c8a29bee02e7117c6"
> X-RateLimit-Limit: 60
> X-RateLimit-Remaining: 57
> X-RateLimit-Reset: 1352660008
> X-GitHub-Media-Type: github.v3
> Vary: Accept
> Cache-Control: public, max-age=60, s-maxage=60
> X-Content-Type-Options: nosniff
> Content-Length: 692
> Last-Modified: Tue, 30 Oct 2012 18:58:42 GMT
> {
> "login": "defunkt",
> "id": 2,
> "url": "http(s)://[hostname]/api/v3/users/defunkt",
> "html_url": "https://github.com/defunkt",
> ...
> }
レスポンスヘッダの中に、ちょっと面白いものがありますね。 思っていたとおり、Content-Type
はapplication/json
です。
X-
で始まるヘッダはすべてカスタムヘッダで、HTTPの仕様にはありません。 例:
X-GitHub-Media-Type
の値はgithub.v3
です。 これは、レスポンスのメディアタイプを伝えています。 メディアタイプは、出力をAPI v3にするために役立ちました。 これについては、後ほど詳しく説明します。X-RateLimit-Limit
とX-RateLimit-Remaining
のヘッダに注目してください。 この2つのヘッダは、1つのローリング期間 (通常は1時間) に1つのクライアントが行えるリクエストの数と、クライアントが既に消費したリクエストの数を示しています。
認証
認証されていないクライアントは、1時間に60件のリクエストを行うことができます。 1時間あたりのリクエストを増やすには、認証が必要です。 実のところ、GitHub Enterprise Server APIを使って何か面白いことがしたければ、認証は欠かせません。
個人アクセストークンの使用
GitHub Enterprise Server APIで認証を行う最も簡単かつ最善の方法は、OAuthトークン経由でBasic認証を使用することです。 OAuthトークンには個人アクセストークンが含まれています。
-u
フラグを使って、ユーザ名を設定します。
$ curl -i -u your_username http(s)://[hostname]/api/v3/users/octocat
プロンプトが表示されたらOAuthトークンを入力できますが、そのための変数を設定することをお勧めします。
トークンをシェル履歴に残すことは避けるべきです。-u "username:$token"
を使用して、token
の変数を設定すると、トークンはシェル履歴に残りません。
$ curl -i -u username:$token http(s)://[hostname]/api/v3/users/octocat
認証の際、X-RateLimit-Limit
ヘッダが示す通り、レート制限が1時間に5,000リクエストに上がったことがわかるはずです。 1時間あたりの呼び出し数が増えるだけでなく、認証するとAPIを使用してプライベート情報を読み書きできます。
個人アクセストークンの設定ページから、簡単に個人アクセストークンを作成できます。
ユーザプロフィールの取得
認証が正しく行われると、GitHub Enterprise Serverアカウントに関連づけられている権限を利用できます。 たとえば、あなたのプロフィールを取得してみましょう。
$ curl -i -u your_username:your_token http(s)://[hostname]/api/v3/user
> {
> ...
> "plan": {
> "space": 2516582,
> "collaborators": 10,
> "private_repos": 20,
> "name": "medium"
> }
> ...
> }
先に@defunktについて取得したパブリックな情報に加えて、今回はユーザプロフィールのパブリックでない情報も表示されているはずです。 たとえば、レスポンスにはplan
オブジェクトが表示されますが、これはアカウントのGitHub Enterprise Serverプランについての詳細です。
OAuthトークンのアプリケーションへの使用
他のユーザに代わりAPIを使用してプライベートな情報を読み書きする必要があるアプリは、 OAuthを使用すべきです。
OAuthはトークンを使用します。 トークンには、次の2つの重要な機能があります。
- アクセスを取り消せる: ユーザはサードパーティアプリケーションへの認可をいつでも取り消すことができます
- 制限付きアクセス: ユーザはサードパーティーアプリケーションを認可する前に、トークンが提供する特定のアクセスを確認できます
トークンはweb フローから作成してください。 アプリケーションはユーザをGitHub Enterprise Serverに送信してログインします。 それからGitHub Enterprise Serverはアプリケーションの名前と、ユーザが認可した場合のアクセス権レベルを示すダイアログを表示します。 ユーザがアクセスを認可すると、GitHub Enterprise Serverはユーザをアプリケーションにリダイレクトします。
OAuthトークンはパスワードと同様に扱ってください。他のユーザと共有したり、安全でない場所に保存したりしてはいけません。 ここにあるトークンのサンプルは架空のものであり、不要な被害を防ぐため名前を変更しています。
さて、これで認証された呼び出しのコツをつかみました。それでは次はリポジトリ APIに進みましょう。
リポジトリ
GitHub Enterprise Server APIを有意義に使用する場合、そのほとんどにおいて何らかのリポジトリ情報が関与します。 以前にユーザ情報をフェッチしたのと同じ方法で、リポジトリ情報をGET
できます。
$ curl -i http(s)://[hostname]/api/v3/repos/twbs/bootstrap
同様に、認証済みのユーザにリポジトリを表示できます。
$ curl -i -H "Authorization: token 5199831f4dd3b79e7c5b7e0ebe75d67aa66e79d4" \
http(s)://[hostname]/api/v3/user/repos
また、別のユーザにリポジトリを一覧表示できます。
$ curl -i http(s)://[hostname]/api/v3/users/octocat/repos
あるいは、Organizationにリポジトリを一覧表示することもできます。
$ curl -i http(s)://[hostname]/api/v3/orgs/octo-org/repos
これらの呼び出しから返される情報は、認証時にトークンが持っているスコープにより異なります。
public_repo
スコープを持つトークンは、github.comで表示するためのアクセス権を持つすべてのパブリックリポジトリを含むレスポンスを返します。repo
スコープを持つトークンは、github.comで表示するためのアクセス権を持つすべてのパブリックリポジトリおよびプライベートリポジトリを含むレスポンスを返します。
Docsに記載されている通り、これらのメソッドはtype
パラメータを取り、これによって、ユーザがリポジトリに対して持つアクセス権に基づき、返されるリポジトリをフィルタリングできます。 こうすることで、直接所有するリポジトリ、Organizationのリポジトリ、またはチームによりユーザがコラボレーションするリポジトリに限定してフェッチすることができます。
$ curl -i "http(s)://[hostname]/api/v3/users/octocat/repos?type=owner"
この例では、octocatが所有するリポジトリのみを取得し、コラボレーションするリポジトリは取得しません。 URLが引用符で囲まれていることに注目してください。 シェルの設定によっては、cURLはURLを引用符で囲まないとクエリ文字列型を無視することがあります。
リポジトリの作成
Fetching information for existing repositories is a common use case, but the
GitHub Enterprise Server API supports creating new repositories as well. To create a repository,
we need to POST
some JSON containing the details and configuration options.
$ curl -i -H "Authorization: token 5199831f4dd3b79e7c5b7e0ebe75d67aa66e79d4" \
-d '{ \
"name": "blog", \
"auto_init": true, \
"private": true, \
"gitignore_template": "nanoc" \
}' \
http(s)://[hostname]/api/v3/user/repos
この最小限の例では、ブログ用の新しいリポジトリを作成しています (GitHub Pagesで提供されるかもしれません)。 ブログはパブリックになりますが、リポジトリはプライベートにしました。 このステップでは、READMEとnanocフレーバーの.gitignore templateによるリポジトリの初期化も行います。
生成されたリポジトリは、https://github.com/<your_username>/blog
にあります。 オーナーであるOrganization以下にリポジトリを作成するには、APIメソッドを /user/repos
から/orgs/<org_name>/repos
に変更するだけです。
次に、新しく作成したリポジトリをフェッチしましょう。
$ curl -i http(s)://[hostname]/api/v3/repos/pengwynn/blog
> HTTP/1.1 404 Not Found
> {
> "message": "Not Found"
> }
あれれ? どこにいったのでしょう。 リポジトリをプライベートにして作成したので、表示するには認証する必要があります。 古参のHTTPユーザの方なら、403
が出ると思っていたかもしれません。 プライベートリポジトリについての情報を漏らしたくはないので、この場合GitHub Enterprise Server APIは404
を返します。「このリポジトリが存在するかは肯定も否定もできない」というようなことです。
問題
GitHub Enterprise ServerのIssue用UIは、「必要十分」なワークフローを提供しつつ、邪魔にならないということを目指しています。 GitHub Enterprise Server Issues APIを使えば、他のツールからデータを引き出したり、Issueを作成したりして、あなたのTeamに合ったワークフローを作成できます。
GitHub.comと同じように、Issues APIは認証されたユーザがIssueを表示するためのメソッドをいくつか提供します。 すべてのIssueを表示するには、GET /issues
を呼び出します。
$ curl -i -H "Authorization: token 5199831f4dd3b79e7c5b7e0ebe75d67aa66e79d4" \
http(s)://[hostname]/api/v3/issues
あなたのGitHub Enterprise Server Organizationのうちの1つのみを取得するには、GET /orgs/<org>/issues
を呼び出します。
$ curl -i -H "Authorization: token 5199831f4dd3b79e7c5b7e0ebe75d67aa66e79d4" \
http(s)://[hostname]/api/v3/orgs/rails/issues
また、1つのリポジトリにあるすべてのIssueを取得することもできます。
$ curl -i http(s)://[hostname]/api/v3/repos/rails/rails/issues
ページネーション
Railsのような規模のプロジェクトになれば、万単位のIssueがあります。 ページネーションを行い、API呼び出しを複数回行ってデータを取得する必要があります。 直近で行った呼び出しを繰り返してみましょう。今回はレスポンスヘッダに注目してください。
$ curl -i http(s)://[hostname]/api/v3/repos/rails/rails/issues
> HTTP/1.1 200 OK
> ...
> Link: <http(s)://[hostname]/api/v3/repositories/8514/issues?page=2>; rel="next", <http(s)://[hostname]/api/v3/repositories/8514/issues?page=30>; rel="last"
> ...
Link
ヘッダは、外部リソースへのリンクに対するレスポンスを提供します。今回の場合は、追加のデータページです。 呼び出しで30 (デフォルトのページサイズ) を超えるIssueを検出したので、APIは次のページと最後のページの場所を伝えます。
Issue の作成
Issueのリストでページネーションを行う方法を確認したので、次はAPIからIssueを作成しましょう。
Issueを作成するには認証される必要があるので、ヘッダにOAuthトークンを渡します。 また、タイトル、本文、およびJSONの本文にあるラベルを、Issueを作成したい、リポジトリ以下の/issues
パスに渡します。
$ curl -i -H 'Authorization: token 5199831f4dd3b79e7c5b7e0ebe75d67aa66e79d4' \
$ -d '{ \
$ "title": "New logo", \
$ "body": "We should have one", \
$ "labels": ["design"] \
$ }' \
$ http(s)://[hostname]/api/v3/repos/pengwynn/api-sandbox/issues
> HTTP/1.1 201 Created
> Location: http(s)://[hostname]/api/v3/repos/pengwynn/api-sandbox/issues/17
> X-RateLimit-Limit: 5000
> {
> "pull_request": {
> "patch_url": null,
> "html_url": null,
> "diff_url": null
> },
> "created_at": "2012-11-14T15:25:33Z",
> "comments": 0,
> "milestone": null,
> "title": "New logo",
> "body": "We should have one",
> "user": {
> "login": "pengwynn",
> "gravatar_id": "7e19cd5486b5d6dc1ef90e671ba52ae0",
> "avatar_url": "https://secure.gravatar.com/avatar/7e19cd5486b5d6dc1ef90e671ba52ae0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png",
> "id": 865,
> "url": "http(s)://[hostname]/api/v3/users/pengwynn"
> },
> "closed_at": null,
> "updated_at": "2012-11-14T15:25:33Z",
> "number": 17,
> "closed_by": null,
> "html_url": "https://github.com/pengwynn/api-sandbox/issues/17",
> "labels": [
> {
> "color": "ededed",
> "name": "design",
> "url": "http(s)://[hostname]/api/v3/repos/pengwynn/api-sandbox/labels/design"
> }
> ],
> "id": 8356941,
> "assignee": null,
> "state": "open",
> "url": "http(s)://[hostname]/api/v3/repos/pengwynn/api-sandbox/issues/17"
> }
レスポンスでは、新しく作成されたIssueに2つのポインタを提供し、それは両方ともLocation
レスポンスヘッダとJSONレスポンスの url
フィールドにあります。
条件付きリクエスト
良きAPI利用者であるために非常に大切なのは、変更されていない情報をキャッシュして、レート制限を尊重するということです。 APIは条件付きリクエストをサポートしており、正しく振る舞うために役立ちます。 最初に呼び出した、Chris Wanstrathのプロフィールを取り上げてみましょう。
$ curl -i http(s)://[hostname]/api/v3/users/defunkt
> HTTP/1.1 200 OK
> ETag: "bfd85cbf23ac0b0c8a29bee02e7117c6"
JSONの本文に加え、HTTPステータスコード 200
とETag
ヘッダに注目してください。 ETagはレスポンスのフィンガープリントです。 後続の呼び出しにこれを渡すと、変更されたリソースだけを渡すようAPIに伝えることができます。
$ curl -i -H 'If-None-Match: "bfd85cbf23ac0b0c8a29bee02e7117c6"' \
$ http(s)://[hostname]/api/v3/users/defunkt
> HTTP/1.1 304 Not Modified
304
ステータスは、直近のリクエストからリソースが変更されておらず、レスポンスには本文が含まれないことを示しています。 特典として、304
レスポンスはレート制限にカウントされません。
ヤッター! これでGitHub Enterprise Server APIの基本が理解できました!
- Basic & OAuth認証
- リポジトリおよびIssueのフェッチと作成
- 条件付きリクエスト
続きのAPIガイドで認証の基本を学びましょう!