Skip to main content

REST API を使用するためのベスト プラクティス

GitHubの API を使用する場合は、次のベスト プラクティスに従ってください。

メモ

レート制限は、サイト管理者がインスタンスを有効にした場合にのみ有効になります。 インスタンスのレート制限が無効になっている場合でも、レート制限を超えないようにするためのベスト プラクティスに従うことをお勧めします。 これは、サーバーの負荷を軽減するのに役立ちます。

ポーリングを回避する

API でデータをポーリングする代わりに、Webhook イベントをサブスクライブしてください。 これにより、統合が API レート制限内に留まるのに役立ちます。 詳しくは、「Webhook ドキュメント」をご覧ください。

Webhook を使用できず、API をポーリングする必要がある場合は、レート制限を超えないようにできるだけ効率的にポーリングします。

  • 必要な頻度でのみ、固定されたスケジュールに従ってポーリングします。 応答に x-poll-interval ヘッダーが含まれている場合は、同じエンドポイントをもう一度ポーリングする前に、少なくともその秒数待ちます。
  • 未変更のデータがプライマリ レート制限に対してカウントされないように、認証済みの条件付き要求を行います。 詳細については、「 条件付き要求を使用する」を参照してください。
  • 必要なデータのみを要求し、応答を安定させ、より多くのポーリングが 304 Not Modified返されるようにします。 詳細については、「 キャッシュ可能な要求を作成する」を参照してください。

認証済みのリクエストを出します。

認証された要求のプライマリ レート制限は、認証されていない要求よりも高くなります。 レート制限を超えないようにするには、認証済みの要求を行う必要があります。 詳しくは、「REST API のレート制限」をご覧ください。

同時にリクエストを行うことを避けてください。

セカンダリ レート制限を超えないようにするには、同時に要求するのではなく、順次要求を行う必要があります。 これを実現するために、要求のキュー システムを実装できます。

変更要求の間で一時停止する

多くの POSTPATCHPUTDELETE リクエストを行う場合は、各リクエストの間を少なくとも 1 秒空けてください。 これは、セカンダリ レート制限を回避するのに役立ちます。

レート制限エラーを適切に処理する

レート制限エラーが発生した場合は、次のガイドラインに従って一時的に要求を停止することが必要です。

  • retry-after 応答ヘッダーが存在する場合は、その秒数が経過するまで要求を再試行しないでください。
  • x-ratelimit-remaining ヘッダーが 0x-ratelimit-reset ヘッダーで指定された時刻 (UTC エポック秒数)が過ぎる まで要求を再試行しないでください。 x-ratelimit-reset ヘッダーは UTC エポック秒単位です。
  • それ以外の場合は、少なくとも 1 分間待ってから再試行します。 要求が二次レート制限により継続して失敗する場合は、再試行の間は指数関数的に増加する時間を待ち、特定の回数の再試行の後にエラーを発生させます。

レート制限中に要求を続けると、統合を禁止する可能性があります。

リダイレクトへの追従

GitHub REST API は、必要に応じて HTTP リダイレクトを使用します。 クライアントは、要求がリダイレクトされる可能性があることを想定する必要があります。 HTTP リダイレクトの受信はエラーではなく、クライアントはそのリダイレクトに従う必要があります。

301 状態コードは、永続的なリダイレクトを示しています。 ヘッダーlocationで指定された URL に要求を繰り返す必要があります。 さらに、今後の要求にこの URL を使用するようにコードを更新する必要があります。

302 または 307 状態コードは、一時的なリダイレクトを示しています。 ヘッダーlocationで指定された URL に要求を繰り返す必要があります。 ただし、今後の要求にこの URL を使用するようにコードを更新しないでください。

その他のリダイレクトステータスコードは、HTTP仕様に従って使用できます。

URL を手動で解析しない

多くの API エンドポイントは、応答本文のフィールドの URL 値を返します。 これらの URL を解析したり、将来の URL の構造を予測したりしないでください。 これにより、 GitHub が将来 URL の構造を変更すると、統合が中断する可能性があります。 代わりに、必要な情報を含むフィールドを探す必要があります。 例えば、問題作成のエンドポイントは、類似の値を持つhtml_urlフィールドと類似のhttps://github.com/octocat/Hello-World/issues/1347number値を持つ1347フィールドを返します。 問題の番号を知る必要がある場合は、number フィールドを使用し、html_url フィールドを解析しないでください。

同様に、ページネーションクエリを手動で作成しないでください。 代わりに、リンク ヘッダーを使用して、要求できる結果のページを決定する必要があります。 詳しくは、「REST API でのページネーションの使用」をご覧ください。

条件付き要求を使用する

ほとんどのエンドポイントはヘッダーを etag 返し、多くのエンドポイントはヘッダーを last-modified 返します。 これらのヘッダーの値を使用して、条件付き GET 要求を行うことができます。 応答が変更されていない場合は、応答を 304 Not Modified 受け取ります。 304 ヘッダーを使って適切に認可された状態で Authorization 応答が返された場合、条件付き要求を行っても、プライマリ レート制限にはカウントされません。 これにより、エンドポイントをポーリングするときに条件付き要求が特に役立ちます。これは、各 304 Not Modified 応答が高速であり、レート制限を使用しないためです。

次の例では、 YOUR-TOKEN をアクセス トークンに置き換えます。 REPO-OWNERをリポジトリを所有するアカウントに置き換え、REPO-NAMEをリポジトリの名前に置き換えます。

etagを使用して条件付き要求を行うには:

  1. 要求を行い、応答から etag ヘッダーの値を保存します。

    curl --include --header "Authorization: Bearer YOUR-TOKEN" http(s)://HOSTNAME/api/v3/repos/REPO-OWNER/REPO-NAME/pulls
    

    応答には、 etag ヘッダーが含まれています。

    HTTP/2 200
    etag: "644b5b0155e6404a9cc4bd9d8b1ae730"
    
  2. 同じ URL への次の要求で、 if-none-match ヘッダーに保存された値を送信します。

    curl --include --header "Authorization: Bearer YOUR-TOKEN" --header 'if-none-match: "644b5b0155e6404a9cc4bd9d8b1ae730"' http(s)://HOSTNAME/api/v3/repos/REPO-OWNER/REPO-NAME/pulls
    

    データが変更されていない場合は、 304 Not Modified 応答が返されます。これは、プライマリ レート制限に対してカウントされません。

    HTTP/2 304
    

last-modified ヘッダーを使用することもできます。 たとえば、前の要求でlast-modifiedヘッダー値Wed, 25 Oct 2023 19:17:59 GMTが返された場合、将来の要求でif-modified-sinceヘッダーを使用できます。

curl --include --header "Authorization: Bearer YOUR-TOKEN" --header 'if-modified-since: Wed, 25 Oct 2023 19:17:59 GMT' http(s)://HOSTNAME/api/v3/repos/REPO-OWNER/REPO-NAME

POSTPUTPATCHDELETE などの安全でないメソッドの条件付き要求は、特定のエンドポイントに関するドキュメントに特に記載されていない限り、サポートされません。

キャッシュ可能な要求を行う

条件付き要求では、エンドポイントから 304 Not Modifiedが返された場合にのみ、時間とレートの制限が節約されます。 エンドポイントは、304またはetag値を保存してから要求した表現が変更されていない場合にlast-modifiedを返します。日付などの関連のない応答ヘッダーは、引き続き異なる場合があります。 ポーリング時に 304 応答の可能性を高めるために、要求を安定して具体的なものにします。

必要なデータのみを要求します。 より小さく、より具体的な応答は頻繁に変更されないため、より頻繁に 304 Not Modified 返されます。 たとえば、1 つのブランチのプル要求を確認するには、すべてのプル要求を一覧表示して自分で結果を検索するのではなく、そのブランチで一覧をフィルター処理します。 HEAD-OWNERをヘッド ブランチを所有するアカウントに置き換えます。フォークからのプル要求の場合、これはフォークを所有するアカウントです。 BRANCH-NAMEをブランチの名前に置き換え、#&などの特殊文字が含まれている場合は URL エンコードします。

curl --include --header "Authorization: Bearer YOUR-TOKEN" "http(s)://HOSTNAME/api/v3/repos/REPO-OWNER/REPO-NAME/pulls?head=HEAD-OWNER:BRANCH-NAME"

リストをページングする場合は、安定した並べ替え順序を使用します。 sort=updatedなどの一部のパラメーターは、項目が変更されるたびにリストの順序を変更します。 項目が新しい位置に移動すると、その古い位置と新しい位置の間の項目が異なるページにシフトするため、既にフェッチしたページは、 304 Not Modifiedではなく新しいデータを返すことができます。 既定などの安定した順序では、既存のアイテムの更新がリストの順序を変更できなくなりますが、項目を追加または削除しても、エントリを他のページにシフトできます。

同じデータをポーリングするたびに、同じパラメーターを使用します。 ページ サイズ、ページ番号、フィルターが異なると、異なる etagで異なる応答が生成されます。

エラーを無視しない

繰り返し発生する4xxおよび5xxエラーコードを無視しないでください。 代わりに、API と正しく対話していることを確認する必要があります。 たとえば、エンドポイントが文字列を要求しているのに数値を渡している場合は、 検証エラーを受け取り、呼び出しは成功しません。 同様に、許可されていないエンドポイントまたは存在しないエンドポイントにアクセスしようとすると、4xx エラーが発生します。

ポーリング中にリソースが 404 Not Found 応答を繰り返し返す場合は、すべてのポーリングで要求し続けないでください。 最初に、 404 が認証または承認によって発生していないことを確認します。 GitHubは、資格情報がアクセスを許可しない場合、一部のプライベート リソースに対する404 Not Found応答ではなく、403 Forbidden応答を返します。そのため、404はリソースが存在しないことを常に意味するとは限りません。 詳しくは、「REST API のトラブルシューティング」をご覧ください。 資格情報が正しいことを確認したら、もう一度確認する前にもっと長く待つか、リソースが存在すると信じる理由がある場合にのみ、もう一度確認してください。 不足しているリソースを繰り返し要求すると、レート制限が無駄になり、セカンダリ レート制限がトリガーされる可能性があります。

繰り返し発生する検証エラーを意図的に無視すると、不正利用によりアプリケーションが停止されることがあります。

参考資料