Google APIs Discovery Service を使用すると、Google API で使用するさまざまなツールを構築できます。ただし、ディスカバリ ドキュメントの主な目的は、Google がさまざまなプログラミング言語でクライアント ライブラリを作成できるようにすることです。このドキュメントでは、Google API にカスタム クライアント ライブラリを作成する方法について説明します。
安定していて機能が完全なクライアント ライブラリは複雑なツールで、開発に数か月かかります。ただし、Google API のシンプルなクライアント ライブラリを構築するための手順は、次の 3 つの簡単なステップにまとめることができます。
- ディスカバリ ドキュメントを取得して API サーフェスを構築する
- リクエストを作成する
- 呼び出しを行ってレスポンスを取得する
手順については、以降のセクションで詳しく説明します。また、「例」セクションのシンプルな API クライアントのサンプルでは、これらの手順とコードがどのように対応しているかを確認することもできます。
ディスカバリ ドキュメントを取得する
クライアント ライブラリの実装を開始する前に、開発過程に影響する基本的な要件がいくつかあります。たとえば、使用するプログラミング言語は型付きのものと、型なしのものがあります。また、型付けを動的に行うものも、静的に行うものもあります。コンパイルまたは解釈が必要な場合もあります。これらの要件により、ディスカバリ ドキュメントの使用方法が決まります。
最初の開発タスクは、ディスカバリ ドキュメントの取得です。ドキュメントを取得する正確なタイミングに関する戦略は、特定した要件によって決まります。たとえば、静的型言語では、プロセスの早い段階でディスカバリ ドキュメントを取得し、そのドキュメントに記述されている特定の API の処理コードを生成します。厳密な型付けを行う言語の場合は、コードを生成し、コンパイル済みのライブラリを構築します。動的型言語の場合、プログラミング構造の構築を遅らせて、プログラミング サーフェスが使用されるときに API とのインターフェースを構築できます。
リクエストを作成する
リクエストの作成には次の 2 つのステップがあります。
- リクエスト本文を作成する。
- リクエスト URL を作成する。
リクエスト本文がある場合は、言語に適した表現を正しい作成形式に変換する必要があります。たとえば、Java クライアント ライブラリでは、リクエスト データの型安全性操作を許可し、JSON にシリアル化可能なリクエスト タイプごとにクラスが存在する場合があります。
リクエスト URL の構成はやや複雑なプロセスです。
API の各メソッドの path
プロパティでは、URI テンプレート v04 構文を使用します。このプロパティには、中かっこで囲まれた変数を含めることができます。変数を含む path
プロパティの例を次に示します。
/example/path/var
上記のパスでは、var
が変数です。この変数の値は、そのメソッドのディスカバリ ドキュメントの parameters
セクションから取得されます。各変数名には、parameters
オブジェクトに対応する値があります。上記の例では、var
という名前のパラメータが parameters
セクションにあります(この location
プロパティは path
で、これがパス変数であることを示します)。
リクエストを行う際は、var
の値を URL に置き換える必要があります。たとえば、ライブラリのユーザーが var
を値 foo
に設定した場合、新しい URL は /example/path/foo
になります。
また、path
プロパティは相対 URI です。絶対 URI を計算する手順は次のとおりです。
-
ロケーション(リージョン)がわかっていて、ディスカバリ ドキュメントに
endpoints
プロパティがある場合は、ロケーションがendpoints
リストに含まれているかどうかを確認します。その場合は、location
が自身のものと一致するendpoints
リストからendpointUrl
を取得します。 -
ディスカバリ ドキュメントに
endpoints
プロパティがない場合、ロケーションがendpoints
リストにない場合、またはグローバル エンドポイントをターゲットにする場合は、最上位のディスカバリ ドキュメントからrootUrl
プロパティを取得します。たとえば、Service Usage API の ディスカバリ ドキュメントの
rootUrl
プロパティは次のとおりです。https://serviceusage.googleapis.com/
-
ディスカバリ ドキュメントの最上位から
servicePath
を取得します。たとえば、Service Usage API のディスカバリ ドキュメントのservicePath
プロパティは空です。 -
これらを連結すると、次のようになります。
https://serviceusage.googleapis.com/
-
path
プロパティを取得し、URI テンプレートとして展開して、その結果を前のステップの URI と結合します。たとえば、v1 Service Usage API のserviceusage.services.enable
メソッドでは、path
プロパティの値はv1/{+name}:enable
です。したがって、このメソッドの完全な URI は次のようになります。https://serviceusage.googleapis.com/v1/{+name}:enable
Service Usage API の呼び出しに API キーは必要ありません。ただし、呼び出す API で API キーが必要な場合は、URI のクエリ文字列にその API キーを追加できます。
REQUEST_URI?key=API_KEY
呼び出しを行い、レスポンスを処理する
リクエストを送信した後、レスポンスのシリアル化を解除して適切な言語表現に変換する必要があります。その際、発生する可能性のあるエラーの状態について、基盤となる HTTP トランスポートと API サービスから生成されたエラー メッセージの両方で確認してください。エラーの形式は、Google JSON スタイルガイドで説明されています。
例
次のセクションでは、API クライアント ライブラリの簡単な例を示します。
シンプルな API クライアント
Python3 で記述された非常にシンプルなクライアント ライブラリの例を次に示します。クライアントは、Service Usage API とやりとりするインターフェースを構築し、そのインターフェースを使用してプロジェクト my-project
で Compute Engine API(compute.googleapis.com
)を有効にします。
import httplib2 import json import uritemplate import urllib # Step 1: Fetch Discovery document DISCOVERY_URI = "https://serviceusage.googleapis.com/$discovery/rest?version=v1" h = httplib2.Http() resp, content = h.request(DISCOVERY_URI) discovery = json.loads(content) location = None # Set this to your location if appropriate use_global_endpoint = True # Set this to False if you want to target the endpoint for your location # Step 2.a: Construct base URI BASE_URL = None if not use_global_endpoint and location: if discovery['endpoints']: BASE_URL = next((item['endpointUrl'] for item in discovery['endpoints'] if item['location'] == location), None) if not BASE_URL: BASE_URL = discovery['rootUrl'] BASE_URL += discovery['servicePath'] class Collection(object): pass def createNewMethod(name, method): # Step 2.b Compose request def newMethod(**kwargs): body = kwargs.pop('body', None) url = urllib.parse.urljoin(BASE_URL, uritemplate.expand(method['path'], kwargs)) for pname, pconfig in method.get('parameters', {}).items(): if pconfig['location'] == 'path' and pname in kwargs: del kwargs[pname] if kwargs: url = url + '?' + urllib.parse.urlencode(kwargs) return h.request(url, method=method['httpMethod'], body=body, headers={'content-type': 'application/json'}) return newMethod # Step 3.a: Build client surface def build(discovery, collection): for name, resource in discovery.get('resources', {}).items(): setattr(collection, name, build(resource, Collection())) for name, method in discovery.get('methods', {}).items(): setattr(collection, name, createNewMethod(name, method)) return collection # Step 3.b: Use the client service = build(discovery, Collection()) print (serviceusage.services.enable(name='projects/my-project/services/compute.googleapis.com'))
クライアントの重要なコンポーネントは次のとおりです。
- ステップ 1: ディスカバリ ドキュメントを取得する。Service Usage API のディスカバリ ドキュメントが取得され、解析されてデータ構造に変換されます。Python は動的型付き言語であるため、ディスカバリ ドキュメントの実行時に取得できます。
- ステップ 2.a: ベース URI を作成する。ベース URI が計算されます。
-
ステップ 2.b: リクエストを作成する。コレクションでメソッドが呼び出されると、メソッドに渡されたパラメータを使用して URI テンプレートが展開され、ロケーション(
query
)を含むパラメータが URL のクエリ パラメータに挿入されます。最後に、ディスカバリ ドキュメントで指定された HTTP メソッドを使用して、作成された URL にリクエストが送信されます。 -
ステップ 3.a: クライアント サーフェスを構築する。クライアント サーフェスは、解析されたディスカバリ ドキュメントで再帰的に降順で構築されます。
methods
セクションのメソッドごとに、新しいメソッドがCollection
オブジェクトに関連付けられます。コレクションはネストできるため、resources
を探し、見つかった場合はすべてのメンバーのCollection
オブジェクトを再帰的に作成します。ネストされた各コレクションは、Collection
オブジェクトの属性としても関連付けられます。 -
ステップ 3.b: クライアントを使用する。構築された API サーフェスがどのように使用されるかを示します。まず、ディスカバリ ドキュメントからサービス オブジェクトが構築され、次に Service Usage API を使用してプロジェクト
my-project
で Compute Engine API が有効になります。