ネットワーク要求のカスタム管理

Microsoft Edge WebView2 コントロールを使用すると、ネットワーク要求を操作および変更できます。 応答を提供するか、 WebResourceRequested イベントと WebResourceResponseReceived イベントを使用してネットワーク要求を変更できます。

NavigateWithWebResourceRequest メソッドを使用して、特定のネットワーク要求を移動できます。

詳細な内容:

概要

Microsoft Edge WebView2 コントロールを使用すると、ネットワーク要求を操作および変更できます。 応答を提供するか、 WebResourceRequested イベントと WebResourceResponseReceived イベントを使用してネットワーク要求を変更できます。

NavigateWithWebResourceRequest メソッドを使用して、特定のネットワーク要求を移動できます。

以下で説明するように、ネットワーク要求を変更できます。 NavigateWithWebResourceRequest メソッドを使用して、次の操作を行います。

  • ローカル ファイルのコンテンツをアプリにアップロードして、オフライン機能のサポートを追加します。

  • 特定の画像など、Web ページ内のコンテンツをブロックします。

  • 特定のページの認証を微調整する。

用語:

用語 定義
intercept ホスト アプリは、WebView2 コントロールから HTTP サーバーに送信された要求をインターセプトし、要求を読み取るか変更し、変更されていないまたは変更された要求を HTTP サーバー (または HTTP サーバーではなくローカル コード) に送信できます。
オーバーライド ホスト アプリは、HTTP サーバーから WebView2 コントロールに送信された応答をオーバーライドし、元の応答の代わりにカスタム応答を WebView2 コントロールに送信できます。

カスタム アプローチと基本的なアプローチをいつ使用するか

WebResourceRequested イベントは、より詳細な制御を提供する低レベルの API ですが、より多くのコーディングが必要であり、使用が複雑です。 一部の一般的なシナリオについては、より使いやすく、特定のシナリオ用に最適化された API が提供されているため、この記事で説明する API ではなく、それらの API を使用することをお勧めします。

WebResourceRequested API を使用する代わりに、可能な場合は次の他の方法を使用することをお勧めします。

メモ: 仮想ホスト名を持つ URL の場合、 WebResourceRequested イベントの使用はサポートされていません。 これは、SetVirtualHostNameToFolderMapping メソッドに対して WebResourceRequested イベントが発生しないためです。

ホスト アプリ、WebView2 コントロール、および HTTP サーバーの相互作用

WebView2 コントロールは、ホスト アプリと HTTP サーバーの間にあります。 ホスト アプリが URI に移動すると、WebView2 コントロールは HTTP サーバーに要求を送信します。 その後、HTTP サーバーは WebView2 コントロールに応答を送信します。

要求をインターセプトして、要求を監視または変更する

ホスト アプリは、WebView2 コントロールから HTTP サーバーに送信された要求を インターセプト し、要求を読み取るか変更し、変更されていないまたは変更された要求を HTTP サーバー (または HTTP サーバーではなくローカル コード) に送信できます。

要求をインターセプトすると、ヘッダーの内容、URL、または GET/POST メソッドをカスタマイズできます。 ホスト アプリは、要求の一部としてオプションの POST コンテンツを提供する要求をインターセプトできます。

ホスト アプリは、次の API を使用して要求のプロパティを変更できます。

ヘッダーで実行できる操作

HTTP ヘッダーは、要求または応答に関する重要な情報とメタデータを提供します。 ヘッダーを変更すると、ネットワーク上で強力なアクションを実行できるようになります。

要求ヘッダーを使用して、応答の形式 (Accept-* ヘッダーなど) の指定、認証トークンの設定、Cookie (機密情報) の読み取りと書き込み、ユーザー エージェントの変更などを行うことができます。 応答ヘッダーを使用して、応答のより多くのコンテキストを提供できます。

URL とリソースの種類に基づく WebResourceRequested イベントのフィルター処理

WebResourceRequested イベントを受信するには、URL とリソースの種類に基づいて、ホスト アプリが関心を持つ要求のフィルターを指定します。

たとえば、ホスト アプリが画像を置き換えようとしているとします。 この場合、ホスト アプリは画像の WebResourceRequested イベントにのみ関心を持ちます。 ホスト アプリは、画像の resourceContext フィルターを指定することによってのみ、画像のイベントを取得します。

別の例としては、ホスト アプリが https://example.com のようなサイトの下にあるすべての要求にのみ関心がある場合です。 その後、アプリは URL フィルターを https://example.com/* として指定して、そのサイトに関連付けられているイベントを取得できます。

URL フィルターの動作の詳細については、「CoreWebView2.AddWebResourceRequestedFilter メソッド > 解説」を参照してください

WebView2 から送信された要求をインターセプトするのはなぜですか?

WebView2 から送信された要求をインターセプトすると、要求をさらに構成できます。 ホスト アプリは、WebView2 コントロールが独自に認識しない要求の一部としてオプションのコンテンツを提供したい場合があります。 次のようなシナリオがあります。

  • ページにログインしていて、アプリには資格情報があるため、ユーザーは資格情報を入力しなくてもアプリは認証ヘッダーを提供できます。
  • アプリでオフライン機能が必要なので、インターネット接続が検出されない場合は、URL をローカルのファイルパスにリダイレクトします。
  • POST 要求によってローカル ファイルのコンテンツを要求サーバーにアップロードする場合。

要求を変更するためのシーケンス

要求を変更するためのシーケンスの図

  1. ホスト アプリが WebResourceRequested フィルターを設定します。
  2. ホスト アプリでは、 WebResourceRequested と WebResourceResponseReceived のイベント ハンドラーを定義します。
  3. ホスト アプリは、WebView2 コントロールを Web ページに移動します。
  4. WebView2 コントロールは、Web ページに必要なリソースの要求を作成します。
  5. WebView2 コントロールは、ホスト アプリに対して WebResourceRequested イベントを生成します。
  6. ホスト アプリは WebResourceRequested イベントをリッスンして処理します。
  7. ホスト アプリはこの時点でヘッダーを変更できます。 ホスト アプリは WebResourceRequested イベントを延期することもできます。つまり、ホスト アプリは、何をすべきかを決定するためにさらに時間を要求します。
  8. WebView2 ネットワーク スタックは、さらにヘッダーを追加できます (たとえば、Cookie と承認ヘッダーを追加できます)。
  9. WebView2 コントロールは、要求を HTTP サーバーに送信します。
  10. HTTP サーバーは、WebView2 コントロールに応答を送信します。
  11. WebView2 コントロールは、 WebResourceResponseReceived イベントを発生させます。
  12. ホスト アプリは WebResourceResponseReceived イベントをリッスンして処理します。

例: 要求をインターセプトして、要求を監視または変更する

次の例では、WebView2 コントロールから http://www.example.com HTTP サーバーに送信されたドキュメント要求をホスト アプリがインターセプトし、カスタム ヘッダー値を追加して要求を送信します。

// Add a filter to select all resource types under http://www.example.com
webView.CoreWebView2.AddWebResourceRequestedFilter(
      "http://www.example.com/*", CoreWebView2WebResourceContext.All);
webView.CoreWebView2.WebResourceRequested += delegate (
   object sender, CoreWebView2WebResourceRequestedEventArgs args) {
   CoreWebView2WebResourceContext resourceContext = args.ResourceContext;
   // Only intercept the document resources
   if (resourceContext != CoreWebView2WebResourceContext.Document)
   {
      return;
   }
   CoreWebView2HttpRequestHeaders requestHeaders = args.Request.Headers;
   requestHeaders.SetHeader("Custom", "Value");
};

応答をオーバーライドして、プロアクティブに置き換える

既定では、HTTP サーバーは WebView2 コントロールに応答を送信します。 ホスト アプリは、HTTP サーバーから WebView2 コントロールに送信された応答を オーバーライド し、元の応答の代わりにカスタム応答を WebView2 コントロールに送信できます。

応答をオーバーライドするシーケンス

応答をオーバーライドするシーケンスの図

  1. ホスト アプリが WebResourceRequested フィルターを設定します。
  2. ホスト アプリでは、 WebResourceRequested と WebResourceResponseReceived のイベント ハンドラーを定義します。
  3. ホスト アプリは、WebView2 コントロールを Web ページに移動します。
  4. WebView2 コントロールは、Web ページに必要なリソースの要求を作成します。
  5. WebView2 コントロールは、ホスト アプリに対して WebResourceRequested イベントを生成します。
  6. ホスト アプリは WebResourceRequested イベントをリッスンして処理します。
  7. ホスト アプリは、 WebResourceRequested イベント ハンドラーへの応答を設定します。 ホスト アプリは WebResourceRequested イベントを延期することもできます。つまり、ホスト アプリは、何をすべきかを決定するためにさらに時間を要求します。
  8. WebView2 コントロールは、応答をリソースとしてレンダリングします。

例: 応答をオーバーライドして事前に置き換える

// Add a filter to select all image resources
webView.CoreWebView2.AddWebResourceRequestedFilter(
      "*", CoreWebView2WebResourceContext.Image);
webView.CoreWebView2.WebResourceRequested += delegate (
   object sender, CoreWebView2WebResourceRequestedEventArgs args) {
   
   // Replace the remote image resource with a local one specified at the path customImagePath.
   // If response is not set, the request will continue as it is.
   FileStream fs = File.Open(customImagePath, FileMode.Open);
   CoreWebView2WebResourceResponse response = webView.CoreWebView2.Environment.CreateWebResourceResponse(fs, 200, "OK", "Content-Type: image/jpeg");
   args.Response = response;
};

カスタム要求を作成し、その要求を使用して移動する

NavigateWithWebResourceRequest メソッドを使用すると、ホスト アプリはカスタム WebResourceRequestを使用して WebView2 コントロール内を移動できます。 この API を使用して、カスタム ヘッダーとコンテンツを持つ GET 要求または POST 要求を作成できます。 次に、WebView2 コントロールはこのカスタム要求を使用して移動します。

例: カスタム要求を作成し、その要求を使用して移動する

// This code posts text input=Hello to the POST form page in W3Schools.

// Need to convert post data to UTF-8 as required by the application/x-www-form-urlencoded Content-Type
UTF8Encoding utfEncoding = new UTF8Encoding();
byte[] postData = utfEncoding.GetBytes("input=Hello");

MemoryStream postDataStream = new MemoryStream(postData.Length);
postDataStream.Write(postData, 0, postData.Length);
postDataStream.Seek(0, SeekOrigin.Begin);

// This acts as a HTML form submit to https://www.w3schools.com/action_page.php
CoreWebView2WebResourceRequest webResourceRequest =
environment.CreateWebResourceRequest("https://www.w3schools.com/action_page.php",
                                     "POST",
                                     postDataStream,
                                    "Content-Type: application/x-www-form-urlencoded");
webView.CoreWebView2.NavigateWithWebResourceRequest(webResourceRequest);

WebResourceResponseReceived イベントによる要求と応答の監視

ヘッダー値を読み取るために、 WebResourceResponseReceived イベントを介して要求と応答を監視できます。

例: WebResourceResponseReceived イベントによる要求と応答の監視

この例では、 WebResourceResponseReceived イベントを介して要求と応答を監視することで、承認ヘッダー値を読み取る方法を示します。

次のコードは、 WebResourceResponseReceived イベントの使用例を示しています。

WebView.CoreWebView2.WebResourceResponseReceived += CoreWebView2_WebResourceResponseReceived;

// Note: modifications made to request are set but have no effect on WebView processing it.
private async void WebView_WebResourceResponseReceived(object sender, CoreWebView2WebResourceResponseReceivedEventArgs e)
{
    // Actual headers sent with request
    foreach (var current in e.Request.Headers)
    {
        Console.WriteLine(current);
    }

    // Headers in response received
    foreach (var current in e.Response.Headers)
    {
        Console.WriteLine(current);
    }

    // Status code from response received
    int status = e.Response.StatusCode;
    if (status == 200)
    {
        Console.WriteLine("Request succeeded!");

        // Get response body
        try
        {
            System.IO.Stream content = await e.Response.GetContentAsync();
            // Null will be returned if no content was found for the response.
            if (content != null)
            {
                DoSomethingWithResponseContent(content);
            }
        }
        catch (COMException ex)
        {
            // A COMException will be thrown if the content failed to load.
        }
    }
}

API リファレンスの概要

要求:

応答:

関連項目