このバージョンの GitHub Enterprise はこの日付をもって終了となりました: 2021-09-23. 重大なセキュリティの問題に対してであっても、パッチリリースは作成されません。 パフォーマンスの向上、セキュリティの改善、新機能のためには、最新バージョンのGitHub Enterpriseにアップグレードしてください。 アップグレードに関する支援については、GitHub Enterprise supportに連絡してください。

REST APIを使ってみる

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

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

ノート: 以下のガイドはGitHub.comのREST APIを使用しています。

  • GitHub Enterprise ServerのAPIにアクセスするためにhttp(s)://[hostname]/api/v3を使ってください。

  • このガイドは、GitHub Enterprise Serverのインスタンスにはないかもしれないユーザ名とリポジトリを指定しています。 同様の出力を得るためには、別の名前を使わなければならないかもしれません。

概要

ほとんどのアプリケーションは、任意の言語において既存のラッパーライブラリを使用しています。ただ、まずは基底となっている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時間あたりのリクエストを増やすには、認証が必要です。 実のところ、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トークンを入力できますが、そのための変数を設定することをお勧めします。

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を使用してプライベート情報を読み書きできます。

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

個人トークンの選択

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

認証が正しく行われると、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について取得した公開情報の同じセットに加えて、あなたのユーザプロフィールのパブリックではない情報もあるはずです。 たとえば、アカウントのGitHub Enterprise Serverプランに関する詳細を持つplanオブジェクトがレスポンス中にあります。

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

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

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

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

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

GitHubのOAuthプロンプト

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 Enterprise Serverのインスタンス上で私たちが見るためのアクセスを持つすべてのパブリック及びプライベートリポジトリを含むレスポンスを返します。

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

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

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

リポジトリの作成

既存のリポジトリ情報をフェッチすることは一般的なユースケースですが、 GitHub Enterprise ServerAPIは新規リポジトリの作成もサポートしています。 リポジトリを作成するには、 詳細情報や設定オプションを含んだいくつかの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が出ると思っていたかもしれません。 プライベートリポジトリについての情報を漏らしたくはないので、この場合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つの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レスポンスはレート制限にカウントされません。

ヤッター! これでGitHub Enterprise Server APIの基本が理解できました!

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

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

問題がまだ解決していませんか?