网络请求的自定义管理
Microsoft Edge WebView2 控件允许你与网络请求交互和修改网络请求。 可以使用 和 WebResourceResponseReceived
事件提供响应或修改网络请求WebResourceRequested
。 还有一个特殊功能,允许你使用 NavigateWithWebResourceRequest API
导航特定的网络请求。
本文介绍如何修改网络请求。 使用此 API 和方法可以:
- 将本地文件内容上传到应用,以添加对脱机功能的支持。
- 阻止网页中的内容,例如特定图像。
- 微调特定页面的身份验证。
术语:
Term | 定义 |
---|---|
拦截 | 主机应用可以截获从 WebView2 控件发送到 HTTP 服务器的请求、读取或修改请求,然后将未更改或修改的请求发送到 HTTP 服务器 (或本地代码,而不是 HTTP 服务器) 。 |
覆盖 | 主机应用可以重写从 HTTP 服务器发送到 WebView2 控件的响应,并将自定义响应发送到 WebView2 控件,而不是原始响应。 |
何时使用自定义方法与基本方法
该 WebResourceRequested
事件是一个低级别 API,可提供更多控制,但需要更多编码,并且使用起来很复杂。 对于某些常见方案,我们提供更易于使用且针对这些特定方案进行了优化的 API,建议使用这些 API,而不是本文中讨论的 API。
最好在可行时使用以下其他方法,而不是使用 WebResourceRequested API:
- 基本身份验证
- 常规导航
- 在 WebView2 中管理 Cookie
- 设置用户代理字符串。 请参阅 UserAgent 属性。
注意: 对于具有虚拟主机名的 URL,不支持使用 WebResourceRequested
事件。 这是因为 WebResourceRequested
不会为 SetVirtualHostNameToFolderMapping 方法触发事件。
主机应用、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 控件自己不知道的请求的一部分。 某些方案包括:
- 你正在登录到页面,并且应用具有凭据,因此应用可以提供身份验证标头,而无需用户输入这些凭据。
- 你需要应用中的脱机功能,以便在未检测到 Internet 连接时将 URL 重定向到本地文件路径。
- 你想要通过 POST 请求将本地文件内容上传到请求服务器。
修改请求的顺序
- 主机应用设置
WebResourceRequested
筛选器。 - 主机应用定义 和
WebResourceResponseReceived
的WebResourceRequested
事件处理程序。 - 主机应用将 WebView2 控件导航到网页。
- WebView2 控件为网页所需的资源创建请求。
- WebView2 控件将
WebResourceRequested
事件触发到主机应用。 - 主机应用侦听并处理
WebResourceRequested
事件。 - 此时,主机应用可以修改标头。 主机应用还可以延迟
WebResourceRequested
事件,这意味着主机应用会要求更多时间来决定要执行的操作。 - WebView2 网络堆栈可以添加更多标头 (例如,可以) 添加 Cookie 和授权标头。
- WebView2 控件将请求发送到 HTTP 服务器。
- HTTP 服务器将响应发送到 WebView2 控件。
- WebView2 控件触发事件
WebResourceResponseReceived
。 - 主机应用侦听
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 控件,而不是原始响应。
重写响应的顺序
- 主机应用设置
WebResourceRequested
筛选器。 - 主机应用定义 和
WebResourceResponseReceived
的WebResourceRequested
事件处理程序。 - 主机应用将 WebView2 控件导航到网页。
- WebView2 控件为网页所需的资源创建请求。
- WebView2 控件将
WebResourceRequested
事件触发到主机应用。 - 主机应用侦听并处理
WebResourceRequested
事件。 - 主机应用设置对事件处理程序的
WebResourceRequested
响应。 主机应用还可以延迟WebResourceRequested
事件,这意味着主机应用会要求更多时间来决定要执行的操作。 - 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 参考概述
请求:
- CoreWebView2.AddWebResourceRequestedFilter 方法
- CoreWebView2.NavigateWithWebResourceRequest 方法
- CoreWebView2.RemoveWebResourceRequestedFilter 方法
- CoreWebView2.WebResourceRequested 事件
- CoreWebView2Environment.CreateWebResourceRequest 方法
- CoreWebView2WebResourceContext 枚举
-
CoreWebView2WebResourceRequest 类
Content
Headers
Method
Uri
-
CoreWebView2WebResourceRequestedEventArgs 类
Request
ResourceContext
Response
GetDeferral
响应:
- CoreWebView2.WebResourceResponseReceived 事件
- CoreWebView2Environment.CreateWebResourceResponse 方法
-
CoreWebView2WebResourceResponse 类
Content
Headers
ReasonPhrase
StatusCode
-
CoreWebView2WebResourceResponseReceivedEventArgs 类
Request
Response
-
CoreWebView2WebResourceResponseView 类
Headers
ReasonPhrase
StatusCode
GetContentAsync
另请参阅
- 从 Web 端代码调用本机端代码
- WebView2 功能和 API 概述中的 Web/本机互操作。