Skip to main content

REST APIを使ってみる

認証とエンドポイントの例から始めて、REST APIを使用するための基礎を学びます。

日常的なユースケースに取り組みながら、APIの中心的な概念を見ていきましょう。

Note: The following guide uses the REST API for GitHub.com.

  • Use http(s)://[hostname]/api/v3 to access the API for GitHub Enterprise Server.

  • The guide specifies usernames and repositories that may not exist on your GitHub Enterprise Server instance. You may need to use different names to see similar output.

概要

ほとんどのアプリケーションは、任意の言語において既存のラッパーライブラリを使用しています。ただ、まずは基底となっているAPI HTTPメソッドについて知ることが大切です。

ちょっと試しにやってみるだけなら、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,
>   "node_id": "MDQ6VXNlcjI=",
>   "avatar_url": "https://avatars.githubusercontent.com/u/2?v=4",
>   "gravatar_id": "",
>   "url": "https://api.github.com/users/defunkt",
>   "html_url": "https://github.com/defunkt",
>   ...
> }

うーん、JSONっぽいですね。 -iフラグを追加して、ヘッダを入れてみましょう。

$ curl -i https://api.github.com/users/defunkt

> HTTP/2 200
> server: GitHub.com
> date: Thu, 08 Jul 2021 07:04:08 GMT
> content-type: application/json; charset=utf-8
> cache-control: public, max-age=60, s-maxage=60
> vary: Accept, Accept-Encoding, Accept, X-Requested-With
> etag: W/"61e964bf6efa3bc3f9e8549e56d4db6e0911d8fa20fcd8ab9d88f13d513f26f0"
> last-modified: Fri, 01 Nov 2019 21:56:00 GMT
> x-github-media-type: github.v3; format=json
> access-control-expose-headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset
> access-control-allow-origin: *
> strict-transport-security: max-age=31536000; includeSubdomains; preload
> x-frame-options: deny
> x-content-type-options: nosniff
> x-xss-protection: 0
> referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
> content-security-policy: default-src 'none'
> x-ratelimit-limit: 60
> x-ratelimit-remaining: 53
> x-ratelimit-reset: 1625731053
> x-ratelimit-resource: core
> x-ratelimit-used: 7
> accept-ranges: bytes
> content-length: 1305
> x-github-request-id: 9F60:7019:ACC5CD5:B03C931:60E6A368
>
> {
>  "login": "defunkt",
>  "id": 2,
>  "node_id": "MDQ6VXNlcjI=",
>  "avatar_url": "https://avatars.githubusercontent.com/u/2?v=4",
>  "gravatar_id": "",
>  "url": "https://api.github.com/users/defunkt",
>  "html_url": "https://github.com/defunkt",
>
>   ...
> }

レスポンスヘッダの中に、ちょっと面白いものがありますね。 思っていたとおり、Content-Typeapplication/jsonです。

X-で始まるヘッダはすべてカスタムヘッダで、HTTPの仕様にはありません。 例:

  • X-GitHub-Media-Typeの値はgithub.v3です。 これは、レスポンスのメディアタイプを伝えています。 メディアタイプは、出力をAPI v3にするために役立ちました。 これについては、後ほど詳しく説明します。
  • X-RateLimit-LimitX-RateLimit-Remainingのヘッダに注目してください。 この2つのヘッダは、1つのローリング期間 (通常は1時間) に1つのクライアントが行えるリクエストの数と、クライアントが既に消費したリクエストの数を示しています。

認証

認証されていないクライアントは、1時間に60件のリクエストを行うことができます。 1時間あたりのリクエストを増やすには、認証が必要です。 In fact, doing anything interesting with the GitHub Enterprise Server API requires authentication.

個人アクセストークンの使用

The easiest and best way to authenticate with the GitHub Enterprise Server API is by using Basic Authentication via OAuth tokens. OAuthトークンには個人アクセストークンが含まれています。

-uフラグを使って、ユーザ名を設定します。

$ curl -i -u your_username http(s)://[hostname]/api/v3/users/octocat

プロンプトが表示されたらOAuthトークンを入力できますが、そのための変数を設定することをお勧めします。

You can use -u "your_username:$token" and set up a variable for token to avoid leaving your token in shell history, which should be avoided.

$ curl -i -u your_username:$token http(s)://[hostname]/api/v3/users/octocat

認証の際、X-RateLimit-Limitヘッダが示す通り、レート制限が1時間に5,000リクエストに上がったことがわかるはずです。 1時間あたりの呼び出し数が増えるだけでなく、認証するとAPIを使用してプライベート情報を読み書きできます。

個人アクセストークンの設定ページから、簡単に個人アクセストークンを作成できます。

個人トークンの選択

ユーザプロフィールの取得

When properly authenticated, you can take advantage of the permissions associated with your account on your GitHub Enterprise Server instance. たとえば、あなたのプロフィールを取得してみましょう。

$ curl -i -u your_username:your_token http(s)://[hostname]/api/v3/user

> {
>   ...
>   "plan": {
>     "space": 2516582,
>    "collaborators": 10,
>    "private_repos": 20,
>    "name": "medium"
>  }
>   ...
> }

今回は、以前に@defunktについて取得した公開情報の同じセットに加えて、あなたのユーザプロフィールのパブリックではない情報もあるはずです。 たとえば、アカウントのGitHub Enterprise Serverプランに関する詳細を持つplanオブジェクトがレスポンス中にあります。

OAuthトークンのアプリケーションへの使用

他のユーザに代わりAPIを使用してプライベートな情報を読み書きする必要があるアプリは、 OAuthを使用すべきです。

OAuthはトークンを使用します。 トークンには、次の2つの重要な機能があります。

  • アクセスを取り消せる: ユーザはサードパーティアプリケーションへの認可をいつでも取り消すことができます
  • 制限付きアクセス: ユーザはサードパーティーアプリケーションを認可する前に、トークンが提供する特定のアクセスを確認できます

トークンはweb フローから作成してください。 アプリケーションはユーザをGitHub Enterprise Serverに送信してログインします。 それからGitHub Enterprise Serverはアプリケーションの名前と、ユーザが認可した場合のアクセス権レベルを示すダイアログを表示します。 ユーザがアクセスを認可すると、GitHub Enterprise Serverはユーザをアプリケーションにリダイレクトします。

GitHubのOAuthプロンプト

OAuthトークンはパスワードと同様に扱ってください。他のユーザと共有したり、安全でない場所に保存したりしてはいけません。 ここにあるトークンのサンプルは架空のものであり、不要な被害を防ぐため名前を変更しています。

さて、これで認証された呼び出しのコツをつかみました。それでは次はリポジトリ APIに進みましょう。

リポジトリ

Almost any meaningful use of the GitHub Enterprise Server API will involve some level of Repository information. 以前にユーザ情報をフェッチしたのと同じ方法で、リポジトリの詳細を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

これらの呼び出しから返される情報は、認証時にトークンが持っているスコープにより異なります。

  • A token with public_repo scope returns a response that includes all public repositories we have access to see on your GitHub Enterprise Server instance.
  • A token with repo scope returns a response that includes all public, private, or internal repositories we have access to see on your GitHub Enterprise Server instance.

Docsに記載されている通り、これらのメソッドはtypeパラメータを取り、これによって、ユーザがリポジトリに対して持つアクセス権に基づき、返されるリポジトリをフィルタリングできます。 こうすることで、直接所有するリポジトリ、Organizationのリポジトリ、またはチームによりユーザがコラボレーションするリポジトリに限定してフェッチすることができます。

$ curl -i "http(s)://[hostname]/api/v3/users/octocat/repos?type=owner"

この例では、octocatが所有するリポジトリのみを取得し、コラボレーションするリポジトリは取得しません。 URLが引用符で囲まれていることに注目してください。 シェルの設定によっては、cURLはURLを引用符で囲まないとクエリ文字列型を無視することがあります。

リポジトリの作成

既存のリポジトリ情報をフェッチすることは一般的なユースケースですが、 GitHub Enterprise Server API supports creating new repositories as well. リポジトリを作成するには、 詳細情報や設定オプションを含んだいくつかのJSONをPOSTする必要があります。

$ 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 テンプレートによるリポジトリの初期化も行います。

生成されたリポジトリは、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/2 404

> {
>    "message": "Not Found"
> }

あれれ? どこにいったのでしょう。 リポジトリをプライベートにして作成したので、表示するには認証する必要があります。 古参のHTTPユーザの方なら、403が出ると思っていたかもしれません。 Since we don't want to leak information about private repositories, the GitHub Enterprise Server API returns a 404 in this case, as if to say "we can neither confirm nor deny the existence of this repository."

Issue

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つのIssueのみを取得するには、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/2 200

> ...
> 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/2 201
> 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/2 200
> etag: W/"61e964bf6efa3bc3f9e8549e56d4db6e0911d8fa20fcd8ab9d88f13d513f26f0"

JSONの本文に加え、HTTPステータスコード 200ETagヘッダに注目してください。 ETagはレスポンスのフィンガープリントです。 後続の呼び出しにこれを渡すと、変更されたリソースだけを渡すようAPIに伝えることができます。

$ curl -i -H 'If-None-Match: "61e964bf6efa3bc3f9e8549e56d4db6e0911d8fa20fcd8ab9d88f13d513f26f0"' \
$    http(s)://[hostname]/api/v3/users/defunkt

> HTTP/2 304

304ステータスは、直近のリクエストからリソースが変更されておらず、レスポンスには本文が含まれないことを示しています。 特典として、304レスポンスはレート制限にカウントされません。

ヤッター! Now you know the basics of the GitHub Enterprise Server API!

  • Basic & OAuth認証
  • リポジトリおよびIssueのフェッチと作成
  • 条件付きリクエスト

続きのAPIガイドで認証の基本を学びましょう!