仕様クラスの変更
ここでは、REST サービスの仕様クラスを変更する方法とその理由を簡単に説明します。
ここでは、"REST サービスの作成と編集" の手順に従って REST サービス・クラスを生成済みであることを前提としています。
概要
以下のテーブルは、仕様クラスを変更する理由をリストし、必要な変更内容を簡単にまとめたものです。
理由 | 変更内容 |
---|---|
仕様を更新または置換する | 手動で、または仕様クラスを再生成することにより、OpenAPI XData ブロックを変更します。 |
REST サービスで CORS のサポートを有効にする | 手動で OpenAPI XData ブロックを変更します。また、クラス・パラメータを追加し、カスタム・ディスパッチ・スーパークラスを作成します。"REST サービスでの CORS のサポート" を参照してください。 |
REST サービスで Web セッションのサポートを有効にする | クラス・パラメータを追加します。"REST での Web セッションの使用" を参照してください。 |
エンドポイントを使用するために必要な特権を指定する | 手動で OpenAPI XData ブロックを変更します。"REST サービスの保護" を参照してください。 |
既定のコンテンツ・タイプ、応答の文字セット、または入力ストリームの処理をオーバーライドする | クラス・パラメータを追加します。次の節を参照してください。 |
サービス・メソッドに既定以外の名前を指定する | 手動で OpenAPI XData ブロックを変更します。"サービス・メソッドの名前のオーバーライド" を参照してください。 |
仕様クラスをコンパイルすると、コンパイラによって、同じパッケージにディスパッチ・クラスが必ず再生成され、実装クラスが更新されます ("インターシステムズにおける実装クラスの更新の動作" を参照してください)。
コンテンツ・タイプ、応答の文字セット、または入力ストリームの処理のオーバーライド
クラス・パラメータを仕様クラスに追加し、リコンパイルするだけで、REST サービスのいくつかの重要な要素をオーバーライドすることができます。
-
既定では、REST サービスは application/json のコンテンツ・タイプを想定します。これをオーバーライドするには、以下のパラメータを仕様クラスに追加します。
Parameter CONTENTTYPE = "some-content-type";
some-content-type は MIME コンテンツ・タイプです。
-
既定では、REST サービスの応答メッセージは UTF-8 形式です。これをオーバーライドするには、以下のパラメータを仕様クラスに追加します。
Parameter CHARSET = "some-character-set";
some-content-type-here は文字セットの名前です。
-
既定では、REST サービスは入力文字ストリームを Unicode に変換します。この処理を行わないようにするには、以下のパラメータを仕様クラスに追加します。
Parameter CONVERTINPUTSTREAM = 0";
その後、リコンパイルします。これにより、これらの変更内容がディスパッチ・クラスにコピーされます。
サービス・メソッドの名前のオーバーライド
既定では、コンパイラは、操作の operationId を使用して、対応する REST 呼び出しによって呼び出されるメソッドの名前を決定します。別の名前を指定することもできます。そのためには、仕様クラスの OpenAPI XData ブロック内の操作に以下を追加します。
"x-ISC_ServiceMethod":"alternatename"
以下に例を示します。
"/pets":{
"get":{
"description":"Returns all pets from the system that the user has access to",
"operationId":"findPets",
"x-ISC_ServiceMethod":"ReturnPets",
"produces":[
"application/json",
"application/xml",
"text/xml",
"text/html"
],
その後、リコンパイルします。これにより、この新しいメソッドがディスパッチ・クラスと実装クラスに追加されます。必ず、実装クラスを編集し、この新しいメソッドの実装を提供してください。
REST サービスでの CORS のサポート
CORS (Cross-Origin Resource Sharing) を使用すると、別のドメインで実行されているスクリプトからサービスにアクセスすることができます。
通常、ブラウザは 1 つのドメインからスクリプトを実行している場合、同じドメインへの XMLHttpRequest の呼び出しを許可しますが、別のドメインへ呼び出される場合は許可しません。このブラウザ動作により、機密データを不正使用するおそれのある悪意のあるスクリプトの作成が制限されます。悪意のあるスクリプトにより、ユーザは与えられた許可を使用して別のドメインの情報にアクセスできますが、ユーザの知らない者が機密情報を他の用途に用いることもできます。こうしたセキュリティの問題を回避するため、通常ブラウザはこの種のクロスドメイン呼び出しを許可しません。
CORS (Cross-Origin Resource Sharing) を使用しない場合、REST サービスにアクセスするスクリプトを使用する Web ページは通常、REST サービスを提供するサーバと同じドメインにある必要があります。一部の環境では、スクリプトを使用する Web ページを REST サービス提供サーバとは異なるドメインに置くと便利です。CORS はこのような配置を可能にします。
以下ではブラウザが CORS で XMLHttpRequest を処理する方法を簡略化して説明します。
-
ドメイン DomOne にある Web ページのスクリプトにはドメイン DomTwo にある InterSystems IRIS データ・プラットフォームの REST サービスへの XMLHttpRequest が含まれます。XMLHttpRequest には CORS のカスタム・ヘッダがあります。
-
ユーザはこの Web ページを閲覧してスクリプトを実行します。Web ページを含むドメインとは異なるドメインへの XMLHttpRequest をユーザのブラウザは検出します。
-
ユーザのブラウザは InterSystems IRIS REST サービスへ特別な要求を送信します。これは XMLHttpRequest の HTTP 要求メソッドおよび元の Web ページのドメイン (この例では DomOne) を示します。
-
要求が許可されると、応答には要求された情報が含まれます。許可されない場合、CORS が要求を許可しなかったことを示すヘッダのみで応答は構成されます。
REST サービスでの CORS のサポートの有効化に関する概要
既定では、インターシステムズの REST サービスは CORS ヘッダを許可しません。ただし、CORS のサポートを有効にすることができます。REST サービスでの CORS のサポートの有効化には、以下の 2 つの部分があります。
-
一部またはすべての HTTP 要求について REST サービスが CORS ヘッダを受け入れるようにします。"CORS ヘッダの受け入れ" を参照してください。
-
REST サービスが CORS 要求を検証し、処理を続行するかどうかを決定するコードを記述します。例えば、信頼されたスクリプトのみを含むドメインを含む許可リストを提供することができます。InterSystems IRIS には、ドキュメント用に単純な既定の実装が用意されています。この既定の実装では、すべての CORS 要求が許可されます。
既定の CORS ヘッダの処理は、機密データを扱う REST サービスには適していません。
CORS ヘッダの受け入れ
REST サービスが CORS ヘッダを受け入れるように指定するには、以下の手順を実行します。
-
仕様クラスを変更して HandleCorsRequest パラメータを追加します。
すべての呼び出しについて CORS ヘッダの処理を有効にするには、HandleCorsRequest パラメータを 1 として指定します。
Parameter HandleCorsRequest = 1;
または、すべてではなく、一部の呼び出しについて CORS ヘッダの処理を有効にするには、HandleCorsRequest パラメータを "" (空の文字列) として指定します。
Parameter HandleCorsRequest = "";
-
HandleCorsRequest パラメータを "" として指定した場合、どの呼び出しで CORS をサポートするかを示すために、仕様クラスの OpenAPI XData ブロックを編集します。具体的には、操作オブジェクトについて、以下のプロパティ名および値を追加します。
"x-ISC_CORS":true
例えば、OpenAPI XData ブロックに以下のような内容が含まれているとします。
"post":{ "description":"Creates a new pet in the store. Duplicates are allowed", "operationId":"addPet", "produces":[ "application/json" ], ...
x-ISC_CORS プロパティを以下のように追加します。
"post":{ "description":"Creates a new pet in the store. Duplicates are allowed", "operationId":"addPet", "x-ISC_CORS":true, "produces":[ "application/json" ], ...
-
仕様クラスをコンパイルします。このアクションによってディスパッチ・クラスが再生成され、実際に動作が変更されます。ディスパッチ・クラスについて詳しく理解する必要はありませんが、以下のように変更されます。
-
HandleCorsRequest パラメータについて指定した値が含まれるようになります。
-
UrlMap XData ブロックに、変更した操作に対応する <Route> 要素について Cors="true" が含まれるようになります。
-
HandleCorsRequest パラメータが 0 (既定値) である場合、CORS ヘッダの処理はすべての呼び出しについて無効になります。この場合、CORS ヘッダを含む要求を REST サービスが受け取ると、サービスはその要求を拒否します。
InterSystems IRIS REST サービスでは、OPTIONS 要求 (CORS プリフライト要求) がサポートされます。これは、REST サービスで CORS がサポートされているかどうかを判別するために使用します。そのような要求を送信するユーザには、REST サービスで使用するあらゆるデータベースに対する READ 許可が必要です。この許可がないと、サービスは HTTP 404 エラーで応答します。代行認証を使用する構成では、認証されたユーザが要求を送信します。ZAUTHENTICATE ルーチンでユーザに適切な許可を割り当てます。代行認証を使用しない構成では、この要求は認証なしで送信され、CSPSystem ユーザが実行します。管理ポータルを使用して適切な許可をユーザに割り当てます。
CORS ヘッダの処理方法の定義
REST サービスが CORS ヘッダを受け入れるようにした場合、既定では、サービスはすべての CORS 要求を受け入れます。REST サービスが CORS 要求を検証し、処理を続行するかどうかを決定するようにする必要があります。例えば、信頼されたスクリプトのみを含むドメインを含む許可リストを提供することができます。そのためには、以下の作業を行う必要があります。
-
%CSP.RESTOpens in a new tab のサブクラスを作成します。このクラスで、最初のサブセクションの説明に従って OnHandleCorsRequest() メソッドを実装します。
-
仕様クラスを変更してリコンパイルし、ディスパッチ・クラスを再生成します。
この結果、ディスパッチ・クラスは、%CSP.RESTOpens in a new tab ではなく、カスタム・クラスを継承するため、既定の CORS ヘッダの処理をオーバーライドする OnHandleCorsRequest() の定義を使用するようになります。
OnHandleCorsRequest() の定義
%CSP.RESTOpens in a new tab のサブクラスで、OnHandleCorsRequest() メソッドを定義します。このメソッドで CORS 要求を検証し、応答ヘッダを適宜設定する必要があります。
このメソッドを定義するには、CORS プロトコルの詳細に精通している必要があります (ここでは説明しません)。
また、要求を検証し、応答ヘッダを設定する方法を理解しておくことも必要です。そのためには、既定で使用されるメソッド、つまり %CSP.RESTOpens in a new tab の HandleDefaultCorsRequest() メソッドを確認すると役立ちます。このセクションでは、このメソッドが起源、資格情報、ヘッダ、および要求メソッドをどのように処理するかを説明し、バリエーションを提示します。この情報を使用して、独自の OnHandleCorsRequest() メソッドを記述することができます。
以下のコードは起源を取得し、それを使用して応答ヘッダを設定します。バリエーションの候補の 1 つは、許可リストに照らして起源をテストすることです。ドメインが許可されている場合、応答ヘッダを設定します。許可されていない場合は、応答ヘッダを空の文字列に設定します。
#; Get the origin
Set tOrigin=$Get(%request.CgiEnvs("HTTP_ORIGIN"))
#; Allow requested origin
Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Origin",tOrigin)
以下の行では認証ヘッダが含まれるように指定します。
#; Set allow credentials to be true
Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Credentials","true")
以下の行では受信する要求からヘッダと要求メソッドを取得します。ヘッダと要求メソッドが許可されているかどうかをテストするコードを記述する必要があります。許可されている場合、それらを使用して応答ヘッダを設定します。許可されていない場合は、応答ヘッダを空の文字列に設定します。
#; Allow requested headers
Set tHeaders=$Get(%request.CgiEnvs("HTTP_ACCESS_CONTROL_REQUEST_HEADERS"))
Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Headers",tHeaders)
#; Allow requested method
Set tMethod=$Get(%request.CgiEnvs("HTTP_ACCESS_CONTROL_REQUEST_METHOD"))
Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Method",tMethod)
既定の CORS ヘッダの処理は、機密データを扱う REST サービスには適していません。
仕様クラスの変更
OnHandleCorsRequest() の実装を含む、%CSP.RESTOpens in a new tab のカスタム・サブクラスを定義したら、以下の手順を実行します。
-
新しいプロパティとして x-ISC_DispatchParent が info オブジェクトに追加されるように、仕様クラスの OpenAPI XData ブロックを編集します。このプロパティの値は、カスタム・クラスの完全修飾名でなければなりません。
例えば、OpenAPI XData ブロックが以下のようであるとします。
"swagger":"2.0", "info":{ "version":"1.0.0", "title":"Swagger Petstore", "description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", "termsOfService":"http://swagger.io/terms/", "contact":{ "name":"Swagger API Team" }, ...
%CSP.RESTOpens in a new tab のカスタム・サブクラスの名前が test.MyDispatchClass であるとします。この場合、XData ブロックを以下のように変更します。
"swagger":"2.0", "info":{ "version":"1.0.0", "title":"Swagger Petstore", "description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", "termsOfService":"http://swagger.io/terms/", "x-ISC_DispatchParent":"test.MyDispatchClass", "contact":{ "name":"Swagger API Team" }, ...
-
仕様クラスをコンパイルします。このアクションによって、ディスパッチ・クラスが再生成されます。このクラスは、カスタム・ディスパッチ・スーパークラスを拡張したものになります。そのため、独自に記述した OnHandleCorsRequest() メソッドを使用するようになります。
REST での Web セッションの使用
REST の目的の 1 つは、ステートレスにすることです。つまり、ある REST 呼び出しから次の呼び出しまでの間、サーバに情報を保存しないということです。複数の REST 呼び出しを通して 1 つの Web セッションを保持することは、ステートレス・パラダイムを崩すことになりますが、1 つの Web セッションを保持する理由が 2 つあります。
-
接続時間を最小限に抑える — REST 呼び出しごとに新しい Web セッションを作成する場合、REST 呼び出しによってサーバ上で新しいセッションを確立する必要があります。Web セッションを保持することで、REST 呼び出しの接続が高速化します。
-
複数の REST 呼び出し間でデータを保持する — 場合によっては、複数の REST 呼び出し間でデータを保持することが、ビジネス要件を効率的に満たすために必要になることがあります。
複数の REST 呼び出しにわたって 1 つの Web セッションを使用できるようにするには、仕様クラスで UseSession パラメータを 1 に設定します。以下に例を示します。
Parameter UseSession As Integer = 1;
その後、このクラスをリコンパイルします。
UseSession が 1 である場合、REST サービスの複数の呼び出しにわたって 1 つの Web セッションが保持されます。このパラメータが 0 (既定値) である場合は、REST サービスの呼び出しごとに新しい Web セッションが使用されます。