このトピックでは、Host ヘッダーに基づいてトラフィックをルーティングする HTTP プロキシ経由でメッセージを送受信するメッセージ プロキシを構成する方法について説明します。HTTP フォワード プロキシは、バックエンド サービス エンドポイントを構成できないモバイル アプリケーションや、バックエンド サービスへの接続に使用するホストとポートを変更するための構成オプションがないテスト対象アプリケーションで使用するのが最適です。
このセクションの内容:
接続設定
基本的な HTTP フォワード プロキシ接続オプションを指定するには、次のサービスおよびリスニング詳細を設定します。
プロキシ設定 (受信)
テスト対象アプリケーションと通信するために、クライアントからのメッセージが接続する場所を指定します。
フォワード プロキシ: メニューからプロキシ作成時に定義したフォワード プロキシ HTTP リスナーを選択するか (「プロキシの作成」を参照)、新しい フォワード プロキシ HTTP リスナーを追加します。このダイアログからフォワード プロキシ HTTP リスナーを追加するには、次の操作を行います。
- [新規] をクリックします。
- リスナーの名前とポートを指定します。
- [OK] をクリックします。
ホスト: トラフィックを監視するサービスのホスト名を指定します。これにより、どのホストが記録されるか、ライブ サービスに送信されるか、仮想アセットに送信されるかが決まります。すべてのトラフィックの監視を許可するには、メニューから [All] を選択します。
パス: リソースで監視するパスを入力します。これは、[ホスト] フィールドに入力された内容と連動して、受信リクエストと照合します。ワイルドカードは使用できません。ホスト上のすべてのパスに一致させるには、このフィールドを空白のままにするか、メニューから [All] を選択します。
受信リクエストに一致する複数のプロキシ接続が設定されている場合、最も一致するホストと最も長いパスの一致が選択され、ホストの一致がより重視されます。たとえば、https://parabank.parasoft.com/parabank/services/bank/customers/12212
という受信ターゲット URL とそれに一致する 4 つのプロキシがあるとします。
- ホスト:
parabank
パス:/parabank
- ホスト:
parabank.parasoft
パス:/parabank/services/bank/customers
- ホスト:
parabank.parasoft.com
パス:/parabank/services_proxy
- ホスト:
parabank.parasoft.com
パス:/parabank/services
このような状況では、プロキシ #4 が選択されます。これは、#2 の方がパスがより正確に一致しているにもかかわらず、#4 の方がホストと一致しており、#3 とは異なり、少なくとも部分的なパスが一致しているためです。
サービス接続 (送信)
プライマリ接続とセカンダリ接続の両方について、ターゲット アプリケーションの仮想アセットまたはメッセージ プロキシへの URL またはパスを指定します。クライアントが要求した元のホストにリクエストをルーティングすることも選択できます。プライマリとセカンダリは同じ方法で設定されます。
- ターゲット アプリケーションの URL を指定するには、メニューから [カスタム] を選択し、URL フィールドにサービス ホスト、サービス ポート、および (オプションで) 転送パスで構成される完全な URL を入力します。サービス URL の各コンポーネントについては、以下の注意事項を参照してください。なお、URL フィールドにクエリ パラメーターを指定した場合、クエリ パラメーターは無視されることに注意してください。
- サービス ホスト: HTTP 接続を消費せずにローカル サーバーの仮想アセットに転送するには、実際のホスト名ではなく、サービス ホストとして host.virt.internal、localhost または 127.0.0.1 を入力します。localhost または
127.0.0.1
を使用する場合、サービス ポートは Virtualize がデプロイされているポートと一致する必要があります。host.virt.internal を使用する場合、サービス ポートは使用されません。たとえば、http://localhost:9080/myVirtualAsset
にデプロイされた仮想アセットには、http://host.virt.internal/myVirtualAsset
を使用してアクセスすることもできます。 - サービス ポート: プロキシがメッセージを送信するポートです。
- 転送パス: [転送パス] を指定しない場合、[プロキシ リスン パス] が使用されます。HTTP プロキシがメッセージを localhost に送信する場合、プロキシは自分自身に転送できないため、転送パスに入力する必要があります。転送パスがリダイレクトを送信する場合、プロキシはリダイレクトを追跡し、応答します。クライアントにはリダイレクトを渡しません。詳細については「サービス転送パスとプロキシ リスン パス」を参照してください。
- サービス ホスト: HTTP 接続を消費せずにローカル サーバーの仮想アセットに転送するには、実際のホスト名ではなく、サービス ホストとして host.virt.internal、localhost または 127.0.0.1 を入力します。localhost または
- ターゲット アプリケーションの仮想アセットまたはメッセージ プロキシへのパスを指定するには、メニューから [仮想化] を選択し、仮想アセットまたはメッセージ プロキシへのパスを [パス] フィールドに入力します。
- クライアントが要求した元のホストにリクエストをルーティングするには、メニューから [パススルー] を選択します。
オプション
モード: プライマリ接続とセカンダリ接続が存在する場合に、アクティブな転送接続を設定できます。たとえば、記録セッション中に、メッセージ プロキシはプライマリ接続としてライブ サービスに転送し、セカンダリ接続として仮想サービスにフォールバックする場合があります。この場合、HTTP モードをプライマリに設定し、[Use other connection if selected mode fails] を有効にすることができます。
記録が完了し、新しい仮想アセットが生成されたら、プロキシを再設定して、最初に仮想サービスに転送し、障害が発生した場合はライブサービスにフォールバックするようにすると良いでしょう。この変更は、プロキシを右クリックして、HTTPモードを「セカンダリ」に切り替えることですぐに適用できます。フェイルオーバーは実行時にそれに応じて調整されます。
Use other connection if selected mode fails: アクティブな接続 (上で選択したモードによって決定される) が失敗したときに、トラフィックをバックアップ プロキシ エンドポイントにリダイレクトしたい場合は、このオプションを有効にします。レスポンスのステータス コードが 400 番台以上の場合、接続が「失敗した」と見なされます。
Bypassing proxy failover
メッセージ レスポンダーは、[Skip message proxy failover] を有効にすることで、内部的にルーティングされるメッセージに対してこのプロキシ フェールオーバーをバイパスするように構成できます。
このオプションが無効な場合、アクティブな接続が記録に使用されます。
このオプションが有効な場合は、[記録] から記録オプションを選択します。
- 両方の接続: プライマリ接続とセカンダリ接続の両方のトラフィックを記録します。アクティブな接続からレポートされたエラー メッセージは記録されません。メッセージはバックアップ接続に送信され、レスポンスが記録されます。バックアップ接続からレポートされたエラーは記録されます。
- プライマリ接続のみ: アクティブな接続のトラフィックを記録します。エラーは記録しません。
- セカンダリ接続のみ: エラーも含め、バックアップ接続のトラフィックを記録します。
有効な HTTP レスポンス コード範囲: メッセージ プロキシのフェイルオーバーの動作をカスタマイズし、200 番台以外のHTTPレスポンス コードを成功とすることができます。コードおよび/またはコードの範囲をカンマで区切って入力します。たとえば「404, 500-599」を使用した場合、「404 のコード」 または「500 番台の任意のコード」が許容されます。
Learn responses: ライブ エンドポイントから記録されたレスポンスを内部エンドポイントにエミュレートするように学習させる場合は、このオプションを有効にします。内部エンドポイントにはファイル レスポンダーが必要です (詳細については「リクエスト/レスポンス ファイル」を参照)。このオプションは、[Use other connection if selected mode fails] が有効になっている場合にのみ使用できます (上記を参照)。プロキシを右クリックしてモードを [すべて有効] または [すべて無効] に切り替えることで、プロキシによる学習の有効/無効を簡単に切り替えることができます。
例: サービスにトラフィックを送信する
http://parabank.parasoft.com
でアクセスされるサービスにメッセージを作成したいと仮定します。次の設定で HTTP フォワード プロキシを作成できます。
- ホスト: parabank.parasoft.com
- サービス ホスト: [Passthrough]
この構成は、ホスト parabank.parasoft.com
に送信されるトラフィックを監視し、トラフィックを通常どおりライブ サービスに渡します。
トラフィックを別のサービス ホストとポートにリダイレクトする場合は、次のようにプロキシの構成を変更できます。
- サービスホスト: coyote.parasoft.com
- サービス ポート: 8080
- サービス転送パス: [空]
これにより、parabank.parasoft.com 宛てのトラフィックが coyote.parasoft.com:8080
の別のサービスにルーティングされます。
例: 仮想アセットにトラフィックを送信する
プロキシはトラフィックを仮想アセットへ送ることもできます。host.virt.internal
のようなローカル仮想ホストまたは組込みの [Virtualize] オプションをサービス ホストとして使用することで、HTTP 接続を使用せずにローカル サーバー上の仮想アセットに転送できます (詳細については前述の「プライマリ接続 (送信) およびセカンダリ接続 (送信)」 を参照)。
これを行う 1 つの方法は、プライマリ発信接続を host.virt.internal
に変更して、トラフィックをローカル サーバー上の仮想アセットに送信することです。
- サービスホスト: host.virt.internal
- サービス ポート: 9080
- サービス転送パス: /path
あるいは、セカンダリ接続はデフォルトでローカルの仮想アセットを指すように構成されているため、モードをプライマリからセカンダリに単純に変更するという方法もあります。
- サービス ホスト: [Virtualize]
- サービス転送パス: /path
- モード: Secondary
Parasoft Root Certificate Authority のインストール
モバイル エミュレーターで HTTP フォワード プロキシを使用する前に、信頼できる証明書として Parasoft Root Certificate Authority をインストールする必要があります。この証明書認証局がインストールされていない場合、ブラウザーは接続がセキュアであるとみなさないため、接続を拒否する場合があります。
Android エミュレーター
この手順では、Android Studio/Android Sdk を使用しており、非運用ビルドで Android Virtual Device (AVD) が作成済みであることを前提としています。さらに:
- AVD のプロキシ設定が Parasoft 用に構成されていること。プロキシでエミュレーターを使用する方法の詳細については、https://developer.android.com/studio/run/emulator-networking#proxy を参照してください。
- Android Sdk エミュレーターと adb 実行可能ファイルを $PATH 変数に追加済みであること。
Android の CA 証明書は、ハッシュ名に拡張子.0を付けて保存されるため、Parasoft の証明書をコピーして名前を変更する必要があります。そのためには、コマンドプロンプトを開き、<VIRT-INSTALL-DIR>/plugins/com.parasoft.ptest.libs.web_<VERSION>/root/lib
に移動して、次のコマンドを実行します。
hashed_name=`openssl x509 -inform PEM -subject_hash_old -in parasoft.cer | head -1` && cp parasoft.cer $hashed_name.0
/system/etc/security/cacerts/
にある Android ファイル システムのシステム証明書ストアに、hash.0 版の CA 証明書を配置する必要があります。ただし、/system
パーティションはデフォルトで読み取り専用としてマウントされるため、まず権限を変更する必要があります。その方法は、使用しているエミュレーターのバージョンによって異なります。
API Level 29 以降
API Level 29 からは、"/" パーティションを read-write 権限で普通にマウントすることができなくなりました。Google は回避策を提供していますが (詳しくは https://android.googlesource.com/platform/system/core/+/master/fs_mgr/README.overlayfs.md を見てください)、これが原因でエミュレーターが起動ループに陥いるケースも見られます。その場合は、以下で説明する回避策を試すことができます。
証明書を使用するには、-writable-system
オプションを使用してエミュレーターを起動する必要があります。そうしないと、Android は「クリーンな」システム イメージをロードします。
AVD を開始します:
emulator -avd <AVD_NAME> -writable-system
- AVD の名前がわからない場合は、
emulator -list-avds
を実行して、すべての AVD のリストを取得します。
- AVD の名前がわからない場合は、
root として adb を再起動します:
adb root
セキュア ブート検証を無効にします:
adb shell avbctl disable-verification
デバイスを再起動し、root として adb を再起動します:
adb reboot adb root
パーティションを read-write として再マウントします:
adb remount
adb から再起動が必要と示された場合は、
adb reboot
とadb remount
を再度実行します。
hash.0 版の証明書をプッシュします:
adb push <PATH_TO_CERT> /system/etc/security/cacerts
証明書のアクセス権限を設定します:
adb shell chmod 664 /system/etc/security/cacerts/<NAME_OF_HASH.0_CERT>
デバイスを再起動します:
adb reboot
API Level 28 以下
証明書を使用するには、-writable-system
オプションを使用してエミュレーターを起動する必要があります。そうしないと、Android は「クリーンな」システム イメージをロードします。
AVD を開始します:
emulator -avd <AVD_NAME> -writable-system
- AVD の名前がわからない場合は、
emulator -list-avds
を実行して、すべての AVD のリストを取得します。
- AVD の名前がわからない場合は、
root として adb を再起動します:
adb root
パーティションを read-write として再マウントします:
adb remount
adb から再起動が必要と示された場合は、
adb reboot
とadb remount
を再度実行します。
hash.0 版の証明書をプッシュします:
adb push <PATH_TO_CERT> /system/etc/security/cacerts
証明書のアクセス権限を設定します:
adb shell chmod 664 /system/etc/security/cacerts/<NAME_OF_HASH.0_CERT>
デバイスを再起動します:
adb reboot
iOS エミュレーター
- ファイル サーバーで parasoft.cer をホストするか、iOS エミュレーターが受信できるアドレスに parasoft.cer ファイルを電子メールで送信します。Parasoft.cer は
<VIRT_INSTALL_DIR>/plugins/com.parasoft.ptest.libs.web_<version>/root/lib.
にあります。 - ブラウザーを開いて parasoft.cer ファイルの URL にアクセスするか、電子メールを開いてダイアログの指示に従い、構成プロファイルを受け入れます。
[設定] > [全般] > [デバイス管理]
に移動し、[Parasoft Root Certificate Authority] を選択します。デフォルト設定のままインストール ダイアログをクリックしていきます。
最近の iOS バージョンでは、Parasoftルート証明書を完全に信頼できるようにする必要があります。次の操作を行います。
[設定] > [全般] > [バージョン情報] > [Certificate Trust Settings]
に移動します。- [Enable full trust for root certificates] で、Parasoft 証明書の信頼を有効にします。