HTTP 受信アダプタの使用法
ここでは、HTTP 受信アダプタ (EnsLib.HTTP.InboundAdapterOpens in a new tab) の既定の動作、およびプロダクションでのこのアダプタの使用法について説明します。
InterSystems IRIS® データ・プラットフォームでは、このアダプタを使用する特殊なビジネス・サービス・クラスとユーザのニーズに適したビジネス・サービス・クラスの 1 つも提供されます。そのため、プログラミングの必要がありません。"接続オプション" を参照してください。
全般的な動作
EnsLib.HTTP.InboundAdapterOpens in a new tab は、カスタム・ポート・リスニング、XML リスニング、または生の HTML 処理に使用する HTTP リスナです。(構成した Web サーバを使用して HTTP 要求を処理する) CSP ページを使用せずに、プライベート・ポートでリッスンしたい場合に、このアダプタを使用します。
まず、このクラスには、以下のような項目の指定に使用する実行時設定が用意されています。
-
アダプタが入力をリッスンするローカル・ポート
-
アダプタが入力を受け入れる IP アドレスのリスト (使用可能なソースを制限したい場合)
-
受信要求で指定された文字セットを使用するかどうかを指定する設定。また、受信要求で指定された文字セットを使用しない場合は、使用する別の文字セット
受信 HTTP アダプタはローカル・マシン上のポートをリッスンし、入力を読み取り、関連するビジネス・サービスにストリームとしてその入力を送信します。ユーザが作成および構成するビジネス・サービスは、このストリームを使用してプロダクションの他の部分と通信します。以下の図は、全体的なフローを示しています。
詳細は、以下のとおりです。
-
アダプタは HTTP メッセージを受信し、TCP 接続を開きます。(HTTP は TCP 接続を介して送信されるヘッダと本文データのフォーマットです。)
-
アダプタが接続されると、その OnConnected() メソッドが実行され、最初に、使用する文字セットが決定されます。デフォルトでは、受信 HTTP 要求で指定された文字セットが使用されます。詳細は、"使用する文字セットの指定" を参照してください。
-
アダプタは、文字セットに対して適切な変換テーブルを選択します。
-
アダプタは、入力の本文を読み取り、変換し、新しいストリーム・オブジェクト内に配置します。
-
アダプタが非バイナリの文字セットを使用している場合、ストリームのタイプは %GlobalCharacterStreamOpens in a new tab です。
-
アダプタがバイナリの文字セットを使用している場合、ストリームのタイプは %GlobalBinaryStreamOpens in a new tab です。
%GlobalCharacterStreamOpens in a new tab および %GlobalBinaryStreamOpens in a new tab は非推奨になっていますが、このような使用法は引き続きサポートされています。このユース・ケースで別のストリーム・クラスに置き換えることはお勧めできません。
また、アダプタは各 HTTP ヘッダを抽出し、ストリームの Attributes プロパティにそのヘッダを追加します。このプロパティは多次元配列です。これについては後述します。
また、URL にフォーム・パラメータが含まれている場合、これらのパラメータは次のように渡されます。
-
HTTP 要求が GET 要求の場合、"Params" 添え字にある Attributes 配列に追加されます。
-
HTTP 要求が POST 要求の場合、要求本文にフォーム変数が書き込まれます。
-
-
次に、アダプタは、ビジネス・サービス・クラスの内部 ProcessInput() メソッドを呼び出し、ストリームを入力引数として渡します。
-
ビジネス・サービス・クラスの内部 ProcessInput() メソッドが実行されます。このメソッドは、すべてのビジネス・サービスが必要とする内部情報の保持など、基本的なプロダクション・タスクを実行します。ビジネス・サービス・クラスが継承するこのメソッドは、カスタマイズや上書きを行いません。
-
次に、ProcessInput() メソッドがカスタムの OnProcessInput() メソッドを呼び出し、ストリーム・オブジェクトを入力として渡します。このメソッドの要件については、この後の "OnProcessInput() メソッドの実装" で説明します。
-
ProcessInput() または OnProcessInput() からエラーが返された場合、プロダクションはビジネス・サービスの OnErrorStream() メソッドを呼び出します。
応答メッセージは、同じパスを逆向きにたどります。
HTTP 受信アダプタを使用するビジネス・サービスの作成
このアダプタをプロダクションで使用するには、ここに記載されているように新しいビジネス・サービス・クラスを作成します。後で、それをプロダクションに追加して、構成します。存在しなければ、適切なメッセージ・クラスを作成する必要もあります。"メッセージの定義" を参照してください。
ビジネス・サービス・クラスの基本要件を以下に列挙します。
-
ビジネス・サービス・クラスは Ens.BusinessServiceOpens in a new tab を拡張するものでなければなりません。
-
クラスの ADAPTER パラメータは EnsLib.HTTP.InboundAdapterOpens in a new tab である必要があります。
-
HTTP POST 要求からのフォーム変数を解析する必要がある場合は、以下のように OnInit() コールバック・メソッドを実装します。
Method OnInit() As %Status { Set ..Adapter.ParseBodyFormVars=1 Quit 1 }
この手順は、GET 要求からのフォーム変数を解析する場合には必要ありません。この後で説明するように、これらは自動的に解析され、Attributes プロパティとして生成されます。
-
このクラスは OnProcessInput() メソッドを実装します。これについては "OnProcessInput() メソッドの実装" で説明します。
-
クラスには OnErrorStream() メソッドを実装できます。"OnErrorStream() メソッドの実装" を参照してください。
-
その他のオプションと一般情報は、"ビジネス・サービス・クラスの定義" を参照してください。
以下の例は、ビジネス・サービス・クラスの全体的な構造を示しています。OnProcessInput() メソッドの詳細は、アダプタが使用している文字セットによって異なります。アダプタが非バイナリの文字セットを使用している場合、全般的な構造は以下のようになります。
Class EHTTP.NewService1 Extends Ens.BusinessService
{
Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";
Method OnProcessInput(pInput As %GlobalCharacterStream, pOutput As %RegisteredObject) As %Status
{
set tsc=$$$OK
//your code here
Quit tsc
}
}
または、アダプタがバイナリの文字セットを使用している場合、OnProcessInput() メソッドは以下のようになります。
Method OnProcessInput(pInput As %GlobalBinaryStream, pOutput As %RegisteredObject) As %Status
{
set tsc=$$$OK
//your code here
Quit tsc
}
OnProcessInput() メソッドの実装
カスタム・ビジネス・サービス・クラスにおいて、OnProcessInput() メソッドのシグニチャは、アダプタが使用している文字セットによって異なります。
-
アダプタが非バイナリの文字セットを使用している場合、シグニチャは以下のようになります。
Method OnProcessInput(pInput As %GlobalCharacterStream, pOutput As %RegisteredObject) As %Status
-
アダプタがバイナリの文字セットを使用している場合、シグニチャは以下のようになります。
Method OnProcessInput(pInput As %GlobalBinaryStream, pOutput As %RegisteredObject) As %Status
ここで、pInput は、アダプタがこのビジネス・サービスに送信する入力です。また、pOutput は、メソッド・シグニチャに必要な汎用出力引数です。
%GlobalCharacterStreamOpens in a new tab および %GlobalBinaryStreamOpens in a new tab は非推奨になっていますが、このような使用法は引き続きサポートされています。このユース・ケースで別のストリーム・クラスに置き換えることはお勧めできません。
OnProcessInput() メソッドは、以下の一部またはすべてを実行する必要があります。
-
入力オブジェクトを調べて、そこから必要なデータを抽出します。"HTTP 要求の使用法" を参照してください。
-
ビジネス・サービスから送信されることになる要求メッセージのインスタンスを作成します。
メッセージ・クラスの作成方法は、"メッセージの定義" を参照してください。
-
要求メッセージに対し、入力ストリームから取得した値を使用して適切にプロパティを設定します。
Attributes プロパティに Content-Type 属性が指定されている場合、デフォルトでは、その属性が要求メッセージの Content-Type として使用されます。Attributes プロパティに Content-Type 属性が指定されていない場合、デフォルトでは、要求メッセージの Content-Type は "text/html" に設定されます。これらのデフォルト値に該当しない場合は、この属性を必ず設定します。例えば、次のコードでは、入力ストリームの Content-Type 属性の値をチェックし、この値がなければ "text/xml" を使用します。
Set outputContentType=$GET(pInput.Attributes("Content-Type"),"text/xml")
-
ビジネス・サービスの適切なメソッドを呼び出して、要求をプロダクション内の宛先に送信します。具体的には、SendRequestSync()、SendRequestAsync()、または (あまり一般的ではない) SendDeferredResponse() を呼び出します。詳細は、"要求メッセージの送信" を参照してください。
これらの各メソッドは、ステータス (具体的には、%StatusOpens in a new tab のインスタンス) を返します。
-
必要に応じて、以前のアクションのステータスを確認し、そのステータスに基づいて対応します。
-
必要に応じて、ビジネス・サービスが受信した応答メッセージを調査し、それに基づいて対応します。
-
必ず出力引数 (pOutput) を設定します。この手順は必須です。
-
適切なステータスを返します。この手順は必須です。
簡単な例を以下に示します。
Method OnProcessInput(pInput As %GlobalCharacterStream, Output pOutput As %RegisteredObject) As %Status
{
//get contents of inbound stream
//in this case, the stream contains a single value: a patient ID
Set id=pInput.Read(,.tSC)
//make sure Read went OK
If $$$ISERR(tSC) do $System.Status.DisplayError(tSC)
//create request object to send
Set tRequest=##class(EHTTP.Request.Patient).%New()
Set tRequest.patientID=id
//send to lookup process
Set tSC=..SendRequestSync("EHTTP.LookupProcess",tRequest,.tResponse)
//define output for OnProcessInput
Set pOutput=tResponse
Quit tSC
}
OnErrorStream() メソッドの実装
ビジネス・サービスの ProcessInput() または OnProcessInput() メソッドからエラーが返された場合、プロダクションはビジネス・サービスの OnErrorStream() メソッドを呼び出します。このメソッドは、必要なエラー処理を含めて実装できます。このメソッドは、ステータス・コードを入力として受け入れ、必要な出力ストリームを返す必要があります。
HTTP 要求の使用法
OnProcessInput() の内部では、HTTP 要求を pInput として利用できます。これは、実装に応じて %GlobalCharacterStreamOpens in a new tab または %GlobalBinaryStreamOpens in a new tab のインスタンスになります。次の図は、このインスタンスで HTTP 要求がどのように表されるかを示しています。
要求の本文は、pInput ストリームに書き込まれます。ストリームの操作の詳細は、"ストリームを使用した作業" を参照してください。
次の項で説明するように、pInput ストリームの Attributes プロパティには、追加のデータが保持されています。これには、HTTP ヘッダが含まれます。要求が GET 要求だった場合は、フォーム変数 (URL パラメータ) もこのプロパティに含まれています。
要求が POST 要求であった場合、フォーム変数は本文にあります。
属性の配列について
pInput ストリームの Attributes プロパティは、以下のデータを保持する多次元配列です。
ノード | コンテンツ |
---|---|
Attributes(http_header_name) (http_header_name は "content-length" のような小文字のヘッダ名) | 指定された HTTP ヘッダの値 |
Attributes("Params",form_variable_name,n) | 指定された URL フォーム変数の n 番目のインスタンスの値 (HTTP 要求が GET 要求だった場合) |
Attributes("URL") | HTTP 要求の完全な URL |
したがって、ヘッダ値を取得するには、次のように指定します。
set contentlength = pInput.Attributes("content-length")
または、変数から URL を取得するには (GET 要求の場合)、次のように指定します。
set pResponse.MessageRequestTimeStamp = pInput.Attributes("Params","REQUESTTIMESTAMP",1)
POST 要求からのフォーム変数の取得
HTTP 要求が POST 要求であった場合、フォーム変数は pInput ストリームにあります。フォーム変数は、& を区切り文字として連結したキーと値のペアです。以下に例を挙げます。
Q1=Answer1&Q2=Answer2&Q3=Answer3
ObjectScript 文字列関数を使用してフォーム変数を取得します。この方法の例を以下に示します。
Method OnProcessInput(pInput As %GlobalCharacterStream, pOutput As %RegisteredObject) As %Status
{
Set tData=pInput.Read(,.tSC)
If $$$ISERR(tSC) {
Do $System.Status.DisplayError(tSC)
}
Set tRequest=##class(EHTTP.Request.Patient).%New()
//use a delimiter to separate the form variables
Set list=$LISTFROMSTRING(tData,"&")
//examine each element and extract the relevant data
Set ptr=0
While $LISTNEXT(list,ptr,key) {
If $PIECE(key,"=") = "Q1" {
Set tRequest.Q1 = $PIECE(key,"=",2)
}
Elseif $PIECE(key,"=") = "Q2" {
SET tRequest.Q2 = $PIECE(key,"=",2)
}
Elseif $PIECE(key,"=") = "Q3" {
Set tRequest.Q3 = $PIECE(key,"=",2)
}
}
Set tSC=..SendRequestSync("EHTTP.LookupProcess",tRequest,.tResponse)
Set pOutput=tResponse
Quit tSC
}
OnInit() コールバック・メソッドを使用して POST 要求のフォーム変数を解析することもできます。
ビジネス・サービスの追加と構成
ビジネス・サービスをプロダクションに追加するには、管理ポータルを使用して以下の操作を行います。
-
カスタム・ビジネス・サービス・クラスのインスタンスをプロダクションに追加します。
-
入力を受信できるようにアダプタを構成します。具体的には、以下を行います。
-
アダプタがリッスンするポートを指定します。そのためには、[ポート] 設定を指定します。
-
アダプタが通信するソースを制限したい場合は、アダプタが入力を受け入れる IP アドレスを指定します (オプション)。
-
入力データの文字セットをオプションで指定します。
-
-
ビジネス・サービスを有効化します。
-
プロダクションを実行します。
HTTP 要求のソースの指定
次の 2 つの方法のいずれかで HTTP 要求のソースを認識するように受信 HTTP アダプタを構成できます。
-
任意のサーバからの HTTP 要求を許可できます。これがデフォルトです。
-
指定のサーバ (必要に応じてポートも指定できます) のリストにあるサーバからの HTTP 要求を許可できます。
そのためには、[許可IPアドレス] 設定を指定します。"HTTP アダプタ設定" を参照してください。
使用する文字セットの指定
EnsLib.HTTP.InboundAdapterOpens in a new tab は、入力を受信すると、その入力内の文字を変換テーブルに従って変換します。使用する変換テーブルを決定するために、アダプタはまず入力に使用されている文字セットを判断します。
通常、入力の HTTP Content-Type ヘッダに、要求が使用している文字セットが示されています。デフォルトでは、アダプタはこの文字セットを使用します。
ただし、以下の実行時設定を使用して、アダプタが使用する文字セットを制御できます。
"HTTP アダプタ設定" を参照してください。
文字セットおよび変換テーブルの詳細は、"変換テーブル" を参照してください。