13 RESTサービスを使用したOracle Database Cloud - Database Schema Service内のデータの操作
Oracle Database Cloud - Database Schema Serviceには、外部アプリケーションがデータを作成、更新、問合せおよび削除するためのRESTサービスが用意されています。
データベース・オブジェクトに直接アクセスするインタフェースを備えたOracle Application Expressを使用して、これらのRESTサービスをOracle Database Cloud - Database Schema Serviceから迅速に定義できます。Oracle Application Expressは、データベース・スキーマ・サービスの顧客にREST機能を提供するためにOracle REST Data Servicesと連携して機能します。
注意:
使用しているサービス用のOracle Application Expressにアクセスするには、Oracle Cloudアカウントにサインインし、サービスのリストでOracle Database Cloud - Database Schema Serviceを選択してから、「サービス・コンソールを開く」ボタンをクリックします。
Oracle Database Cloud - Database Schema Serviceには、データベース・オブジェクトに対するGET、POST、PUTおよびDELETE操作が用意されており、これらは、SQLコマンドまたは匿名PL/SQLブロックの実行につながります。
これらのRESTサービスには、次の2つの主な目的があります。
-
外部データのロード
-
このデータ上に構築されたUIに対するRESTベースのアクセス・メカニズムの提供
たとえば、JCS - SaaS Extensionインスタンスにクライアント側のアプリケーションをデプロイすることにより、KnockoutJSベースのアプリケーションを構築してOracle Database Cloud - Database Schema Service上のデータにアクセスできます。
既存のRESTサービスへのアクセス
Oracle Application Express内のSQLワークショップ・モジュールを使用して、RESTサービスにアクセスできます。
http://dbcs_service_instance_URL/apex/service_module_URI_prefix/resource_URI_template
URIの接頭辞によって識別されるRESTサービス・モジュールは、特定のビジネス機能に対して使用可能な複数の関連リソースのグループです。また、これらのリソースは、リソース・テンプレートを介して定義され、URIテンプレートによって識別されます。したがって、各RESTサービス・モジュールは、複数のリソース・テンプレートで構成されています。
上記の例では、hr/
は、HRの関連オブジェクト(つまり、EMPおよびDEPT)にアクセスするために使用可能なすべてのRESTリソースをグループ化するRESTサービス・モジュールのURIの接頭辞です。リソース・テンプレートempinfo/
により、JSONフォーマットの従業員情報にアクセスできるようになります。
RESTサービスの作成
Oracle Application Expressを使用して、RESTサービスを宣言して作成できます。REST APIは、APIを介して公開される論理エンティティであるリソースに対して機能します。たとえば、Oracle Database Cloud - Database Schema Serviceインスタンス内のデータベース表にリソースをマップできます。
RESTサービスの作成に関するベスト・プラクティス
RESTサービス(または通称のREST API)を作成する前に、RESTful APIの定義に関する一般的なベスト・プラクティスについて理解してください。
これらのベスト・プラクティスをまだ把握していないか、組織内で標準が確立されていない場合は、次のガイドラインを開始点として使用してください。
詳細なリソースの公開
最も簡単なフォームにおいて、リソースをデータベース表にマップできますが、すべてのデータベース表に対してREST APIを作成しても意味がない場合があります。たとえば、参照表に対してREST APIを作成することが必要ないこともあります。REST APIでは、粒度の粗いリソースを公開する必要がありますが、バックグラウンドでは、関連APIの実装が複数のデータベース・オブジェクトに対して動作している場合があります。たとえば、従業員はリソースになります。従業員を作成するには、APIユーザーに対して透過的である必要がある参照表または部門表の操作が必要になる場合があります。
リソースは、動詞(getEmployees
)ではなく、複数形の名詞(employees
)である必要があります。リソースは、HTTPメソッドと連携して機能します。Oracle Database Cloud - Database Schema ServiceによってサポートされているHTTPメソッドは、GET、PUT、POSTおよびDELETEです。
RESTサービスの一般的な使用方法
一般的な使用方法の場合、GETを使用して1つ以上のリソースを取得し、POSTを使用してリソースを作成し、PUTを使用してリソースを更新し、DELETEを使用してリソースを削除します。次に例を示します。
-
GET /employees: すべての従業員を取得します。
-
GET /employees/{id}: 特定の従業員IDを持つ従業員を取得します。
-
POST /employees: 新しい従業員を作成し、従業員IDをURIとして返します。
-
PUT /employees/{id}: 特定の従業員IDを持つ従業員を更新します。
-
DELETE /employees/{id}: 特定の従業員IDを持つ従業員を削除します。
PUTおよびPOSTの使用方法は、シナリオによって異なる可能性があります。この例では、従業員IDがデータベース順序によって生成されることを想定しています。したがって、作成用としてPOSTを使用しました。APIのコンシューマが作成対象の従業員の従業員IDを指定できる場合、かわりにPUTメソッドを使用できます。
他のリソースおよびフィルタとの関係
他のリソースとの関係を表すには、次のようにAPIをモデル化できます。
-
GET /departments/{id}/employees: 部門IDによって識別される特定の部門に属するすべての従業員を取得します。
-
POST /departments/{id}/employees: 特定の部門の新しい従業員を作成します。
(関係に基づかずに)レコードをフィルタする場合、一般的なベスト・プラクティスは、次のようなURL問合せパラメータを使用する方法です。
GET /departments?location={location}
ソートは、次のようなソートURLパラメータを導入することによって実現できます。
GET /departments?location={location}&NS=<sort-key-name>|<sort-order(0 or 1)>
この場合:
-
<sort-key-name>は、ソート基準にする列名です。
-
<sort-order>は、レコードをソートする順序です。0は昇順で、1は降順です。
前述のとおり、REST APIを定義する場合、これらのガイドラインを開始点として使用します。Oracle Database Cloud - Database Schema Serviceインスタンスに定義されているすべてのREST APIが一貫したアプローチに従っていることを確認してください。oracle.example.hrサンプル・モジュールで提供する例では、従業員データにアクセスするための複数のAPI (リソース・テンプレート)を示しています。
注意:
RESTfulの例を参照するには、「SQLワークショップ」ページに移動し、「RESTfulサービス」ボタンをクリックし、「RESTfulサービス」ページを開きます。このアプローチは、Oracle Database Cloud - Database Schema Serviceで使用可能な複数の構成オプションを示すことのみを目的として使用しました。ビジネス・ニーズに応じて、ベスト・プラクティスおよび組織の標準に基づいて必要となるリソース・テンプレートのみを作成する必要があります。
データを挿入するためのREST APIの作成
このドキュメントでは、DEPTサンプル表にレコードを挿入するためにOracle Application Express REST APIを作成する方法について説明します。
RESTfulリソースの作成
-
-
Oracle Application Expressのメイン・ページで、「SQLワークショップ」ボタンをクリックしてから、「RESTfulサービス」をクリックします。
このページには、既存のRESTサービス・モジュールがリストされます。前述のとおり、モジュールは、目的がPL/SQLパッケージと似ている、関連リソース・テンプレートのグループです。
-
サービス・モジュールを選択します。ここでは、別のHR関連リソースであるDEPTを操作するため、oracle.example.hrサービス・モジュールをクリックします。
DEPTリソースにアクセスするには、最初にoracle.example.hrサービス・モジュールの下でリソース・テンプレートを作成する必要があります。ナビゲーション・バーで、下部までスクロールし、「テンプレートの作成」をクリックします。
-
次のように「リソース・テンプレート」ページを完了します。
-
URIテンプレートを指定します。
前に説明したベスト・プラクティスに従い、「URIテンプレート」フィールドに「departments/」と入力します。フォワード・スラッシュは意図的なものであり、テンプレートの各種要素をURIとして表示するときに区別しやすくなります。
-
優先度を設定します。
優先度により、競合の可能性を回避するためにリソース・テンプレートを実行する順序が決まります。一致するテンプレートが複数存在するときにOracle Application Expressが実行すべき処理内容を評価しやすくしようとする場合、優先度の設定が役に立ちます。たとえば、APIリクエストが
employees/{id}
として設定されている場合、employees/{id}
とemployees/{id}/departments
の両方が一致します。異なる優先度を指定すると、このような競合を解決しやすくなります。この例では、デフォルト値の0のままにします。 -
エンティティ・タグを定義します。
エンティティ・タグは、APIレスポンスのコンテンツに基づいて生成される一意の値です。この値は、HTTPヘッダーで返され、リソースの値が変更されたかどうかを確認するために後続の起動時に使用できます。この確認では、リソースの状態が変更されていない限り、リソースの取得を回避します。一意の値を生成するために使用されるアルゴリズムを表すデフォルト値のSecure HASHのままにします。
-
「作成」をクリックします。
departments/テンプレートは、ダッシュボード内に表示されます。
-
-
このリソース・テンプレートのハンドラを作成します。ハンドラは、リソース・テンプレートに関連付けられた各HTTPメソッドの実装ロジックを提供します。
-
departments/テンプレートの下で、「ハンドラの作成」をクリックします。
-
「方法」フィールドで、「POST」を選択します。
-
「ソース・タイプ」フィールドで、唯一使用可能な値として「PL/SQL」を選択します(なぜなら、これがPOST操作であるためです)。
-
「セキュア・アクセスが必要」フィールドで、「はい」を選択します。このフィールドは、APIがSSLを介してのみアクセス可能であるかどうかを示します。
-
「ソース」フィールドで、次のPL/SQLコードを入力します。
declare dnum integer; begin insert into dept (dname, loc) values (:name,:loc) returning deptno into dnum; :deptnum := dnum; :status :=201; end;
このサンプル・コードでは、
name
およびloc
は入力バインド変数であり、deptnum
およびstatus
は出力用として使用されます。 -
「作成」をクリックし、ハンドラを作成します。
-
-
出力バインド変数に対応するHTTPパラメータの作成
-
-
「パラメータの作成」をクリックします。
-
「名前」フィールドで、「X-APEX-FORWARD」と入力します。
-
「バインド変数名」フィールドで、「deptnum」と入力します。
-
「アクセス方法」フィールドが、アウトバウンド・パラメータを示す「OUT」に設定されていることを確認します。
-
「ソース・タイプ」フィールドで、「HTTPヘッダー」を選択します。
-
「パラメータ・タイプ」ドロップダウン・リストから「文字列」を選択します。
-
「作成」をクリックします。
X-APEX-FORWARD
は、Oracle REST Data Servicesが認識する特別なHTTPヘッダー名です。「ソース」フィールドでこのパラメータに値が割り当てられている場合、この値を使用して、新しく挿入されたレコードが自動的に取得され、その表現(JSONフォーマットなど)がコール元に返されます。これが役に立つのは、POSTリクエストを送信したコール元が、新しいレコード用として生成された主キー値を把握する必要がある場合です。ただし、この機能では、departments/{id}
リソース・テンプレートとGETハンドラが同じRESTモジュール内に定義されていることが必要です(そうでない場合、 404 Not Found レスポンスがPOSTリクエストに対して返されます)。X-APEX-FORWARD
パラメータはオプションです。説明した機能を活用する予定がない場合、このパラメータをRESTハンドラに定義する必要はありません。同様に、
X-APEX-STATUS-CODE
と呼ばれる別のパラメータを作成し、「バインド変数名」フィールドを次のように割り当てます: 「status」。X-APEX-STATUS-CODE
はまた、Oracle REST Data Servicesが実際のHTTPレスポンス・ステータスを操作するために使用する特別なHTTPヘッダーでもあります。 -
入力バインド変数の使用
入力バインド変数に値を提供するメカニズムは少なくとも3つあります。次の3つの各ステップでは、異なるメカニズムについて説明します。ニーズに適したメカニズムを選択してください。
- HTTPパラメータを使用して値をバインドする手順:
-
-
「パラメータ」セクションで、「パラメータの作成」をクリックします。
-
「名前」フィールドで、「X-DEPTNAME」と入力します。
-
「バインド変数名」フィールドで、「name」と入力します。
-
「アクセス方法」フィールドが、インバウンドHTTPヘッダーを示す「IN」に設定されていることを確認します。
-
「ソース・タイプ」フィールドで、「HTTPヘッダー」を選択してから、「パラメータ・タイプ」ドロップダウン・リストから「文字列」を選択します。
-
「作成」をクリックします。
-
同様に、「バインド変数名」を「loc」として、X-DEPTLOCと呼ばれる別のHTTPパラメータを作成します。
このREST APIをテストするために、
cURL
を使用します。または、他の任意のRESTクライアントを選択して使用することもできます。curl -X POST -v "https://dbcs_service_instance_URL/apex/hr/departments/" -H "X-DEPTNAME: Marketing" -H "X-DEPTLOC: Boston"
次に 200 OK HTTPステータスが、次のようなJSONレスポンスとともに返されます。
{"deptnum":"100"}
注意:
dbcs_service_instance_URLを取得するには、Oracle Cloudアカウント(https://cloud.oracle.com)にサインインします。マイ・サービスから、Oracle Database Cloud - Database Schema Serviceインスタンスを選択します。このページにサービス・インスタンスURLが表示されます。 -
- ペイロードとしてのJSONの使用
-
多くの場合、JSON入力を介してパラメータ値を指定することをお薦めします。表に複数のデータ列を挿入する場合は特に、この方法が役に立ちます。JSONペイロードを指定する場合、Oracle Database Cloud - Database Schema Serviceにより、JSONが解析され、値がバインド変数に変換されます。たとえば、バインド変数nameおよびlocは、次のJSONペイロードから自動的に抽出されます。
{ “name”: “Marketing”, “loc”: “Boston” }
この場合、HTTPパラメータは必要ないため、INパラメータを作成した場合はリソースからこれらのパラメータを削除します。
cURL
を使用して、JSONペイロードを使用してこのREST APIをテストします。curl -X POST -v "https://dbcs_service_instance_URL/apex/hr/departments/" -H "Content-Type: application/json" -d '{"name":"XXXX", "loc":"YYY"}'
次のようなJSONレスポンスが返されます。
{"deptnum":"100"}
現在、Oracle Database Cloud - Database Schema Serviceでは、単一でネストしていないJSONペイロードのみを自動的に処理できます。つまり、配列であるかネストされたJSONペイロードを使用する場合、JSONからPL/SQLバインド変数へのこの自動変換を使用することはできません。より複雑なJSONを使用する場合、APEX_JSONまたは他のアプローチを使用して、リソース・ハンドラのPL/SQLコード・ブロックで値を手動でバインド変数に変換する必要があります。
『Oracle Application ExpressAPIリファレンス』のAPEX_JSONに関する項を参照してください。 - フォームURLエンコーディング・フォーマットの使用
-
場合によっては、このタイプのREST APIに対してユーザー・インタフェースを構築する場合は特に、入力ペイロード用としてフォームURLエンコーディング・フォーマットを使用することをお薦めします。Oracle Database Cloud - Database Schema Serviceでは、JSONフォーマットの場合で見られるように、ペイロード内のキーと値をバインド変数と値として自動的に変換できます。「コンテンツ・タイプ」がapplication/x-www-form-urlencodedに設定されていることを確認してください。
データを問い合せるためのREST APIの作成
このドキュメントでは、データを問い合せるためにOracle Application Express REST APIを作成する方法について説明します。
作成可能な追加のリソース・テンプレートは、次のとおりです。
-
特定の部門を返す、GETハンドラを使用した
departments/{id}
-
特定の場所の部門をすべて返す、GETハンドラを使用した
departments?loc={loc}
どちらの場合も、URIのソース・タイプのパラメータを作成し、問合せで使用するバインド変数にこれらをリンクします。URI問合せパラメータは、自動的にSQLバインド変数に変換されます。
注意:
パラメータの作成時にURIのソース・タイプが表示されない場合、「ソース・タイプ」フィールドを「HTTPヘッダー」に設定することにより、パラメータを作成します。作成したら、パラメータ表から選択してパラメータを再編集し、「ソース・タイプ」フィールドを「URI」に変更します。
RESTサービスの保護
REST APIは、少なくとも次の2つの方法で保護できます。
-
リソース・モジュールの保護および認証の強制: 外部アプリケーションは、これらの保護リソースに対して認証する必要があります。
-
ロジック・ベースのアクセスの使用: 暗黙的なユーザー識別バインド変数を活用してリソース・ハンドラにコード・ロジックを追加します。この場合、認証は関係ありません。
リソース・モジュールの保護および認証の強制
権限を使用して、リソース・モジュールを保護し、アクセスに対する認証を強制できます。
必要な権限を持ち、正常に認証できるユーザーのみが、RESTサービスにアクセスできます。
認証の強制
OAuth 2.0を使用して、REST APIに対して認証を強制します。
IETFのWebサイトの「OAuth 2.0認可フレームワーク」ドキュメントを参照してください。
OAuthを設定するには、このAPIにアクセスするユーザーが先に、RESTfulサービス権限に関連付けられたRESTfulサービス・ユーザー・グループに属している必要があります。簡略化のために、独自のユーザー・アカウントを構成できます。
アカウントを設定する手順:
-
任意のOracle Application Expressページから、メイン・ツールバーの「ヘルプ」アイコンの横にあるドロップダウン・メニューをクリックし、「管理」にナビゲートします。
-
「ユーザーとグループの管理」ボタンをクリックします。
-
「ユーザー名」をクリックし、プロファイルを開きます。
-
「グループ割当て」セクションにナビゲートし、次のユーザー・グループに割り当てられていることを確認します。
-
RESTfulサービス
-
OAuth2クライアント
-
注意:
OAuthを登録するには、Oracle Database Cloud - Database Schema Serviceインスタンス用のデータベース管理者ロールがある必要があります。詳細は、Oracle Cloud管理者に連絡してください。認証メカニズムとしてのOAuth 2.0の構成
ステップ2: 認可コードの取得
認可コードを取得するには、次のURIを使用します。
https://dbcs_service_instance_URL/apex/oauth/auth?response_type=code&client_id=CLIENT_IDENTIFIER&state=STATE
STATEは、クロスサイト・リクエスト・フォージェリ(CSRF)攻撃を防止するために使用するランダム値です。OWASPのWebページの「クロスサイト・リクエスト・フォージェリ(CSRF)」を参照してください。ユーザーがリクエストを承認すると、ブラウザが登録したリダイレクトURIにリダイレクトされます。URIの問合せ文字列部分でアクセス・トークンがエンコードされます。
https://example.demo.com?code=AUTHORIZATION CODE&state=STATE
送信したSTATE値が受信したSTATE値と同じであることを確認してください。登録したhttps://example.demo.com
リダイレクトURIは存在しないため、ブラウザでは、サーバーが見つからないエラーがレポートされます。この例の目的上、URIにエンコードされた認可コード値は依然として表示されるため、このエラーは問題ありません。認可コード・パラメータの値をメモしてください。
ステップ3: アクセス・トークンの取得
アクセス・トークンを取得するには、次のcURL
コマンドを使用します。
curl -i -d "grant_type=authorization_code&code=AUTHORIZATION_CODE" -user CLIENT_IDENTIFER:CLIENT_SECRET https://dbcs_service_instance_URL/apex/oauth/token
このコマンドにより、次のようなレスポンスが生成されます。
{ "access_token":"04tss-gM35uOeQzR_2ve4Q..", "token_type":"bearer", "expires_in":3600, "refresh_token":"UX4FVHhPFJl6GokvTXYw0A.."}
このレスポンスは、アクセス・トークンとともにリフレッシュ・トークンが含まれるJSONドキュメントです。
ステップ4: リソースへのアクセス
ここで、保護されたREST APIに対して行われる各リクエストとともにアクセス・トークンを含める必要があります。
これを行うには、次の構文を使用して認可ヘッダーをHTTPリクエストに追加する必要があります。
Authorization: Bearer ACCESS_TOKEN
ステップ5: アクセス・トークンのリフレッシュ
OAuth 2.0セッションの存続期間を延長するには、リフレッシュ・トークンを、新しい有効期間を持つ新しいアクセス・トークンに交換できます。この交換は、アプリケーションがプログラムで処理できます。
リフレッシュ・トークンをアクセス・トークンに交換するには、次のcURL
コマンドを使用します。
curl -i -d "grant_type=refresh_token&refresh_token=REFRESH_TOKEN" –user CLIENT_IDENTIFER:CLIENT_SECRET https://dbcs_service_instance_URL/apex/oauth/token
このコマンドにより、次のようなレスポンスが生成されます。
{ "access_token":"hECH_Fc7os2KtXT4pDfkzw..", "token_type":"bearer", "expires_in":3600, "refresh_token":"-7OBQKc_gUQG93ZHCi08Hg.."}
このレスポンスは、新しいアクセス・トークンとともに新しいリフレッシュ・トークンが含まれるJSONドキュメントです。既存のアクセス・トークンとリフレッシュ・トークンは無効化されます。古いアクセス・トークンを使用してサービスにアクセスしようとすると、閲覧禁止HTTP - 403ステータス・コードが生成されます。
ロジック・ベースのアクセスの使用
この値は標準WHERE句の一部として使用できます。たとえば、これを使用して、問合せから返される行を、現在のユーザーと同じ部門の行に制限できます。また、この値は、SQLまたはPL/SQLのより複雑なロジックで使用することもできます。
前の2つのメカニズムに加えて、RESTfulサービス・モジュールでは、リソース・テンプレートへのアクセスが許可されたクライアント・アプリケーションURLのカンマ区切りのリストを指定することもできます。この情報は、「使用可能な起点」フィールドを使用してモジュール定義で定義します。たとえば、https://*.example.comの値を指定すると、example.com
WebサイトからのみこのAPIにアクセスできるようになります。