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

Microsoft Edge WebView2 コントロールを使用すると、ネットワーク要求を操作および変更できます。 応答を指定するか、 イベントと WebResourceResponseReceived イベントを使用してネットワーク要求をWebResourceRequested変更できます。 また、 を使用して特定のネットワーク要求を使用 NavigateWithWebResourceRequest APIして移動できる特別な機能もあります。

この記事では、ネットワーク要求を変更する方法について説明します。 次の API とアプローチを使用します。

  • ローカル ファイル コンテンツをアプリにアップロードして、オフライン機能のサポートを追加します。
  • 特定の画像など、Web ページ内のコンテンツをブロックします。
  • 特定のページの認証を微調整します。

用語:

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

カスタムアプローチと基本アプローチを使用するタイミング

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

WebResourceRequested API を使用する代わりに、可能であれば、次の他の方法を使用することをお勧めします。

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

ホスト アプリ、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 取得します。

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

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

WebView2 から送信された要求をインターセプトする理由

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

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

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

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

  1. ホスト アプリはフィルターを WebResourceRequested 設定します。
  2. ホスト アプリは、 と WebResourceResponseReceivedのイベント ハンドラーをWebResourceRequested定義します。
  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 サーバーに送信されるドキュメント要求を インターセプトhttp://www.example.com 、カスタム ヘッダー値を追加して要求を送信します。

// 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. ホスト アプリは、 と WebResourceResponseReceivedのイベント ハンドラーをWebResourceRequested定義します。
  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メソッドを使用すると、ホスト アプリでカスタム を使用して WebView2 コントロール内を移動できますWebResourceRequest。 この 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 リファレンスの概要

要求:

応答:

関連項目