WebUI3中的WebView2:如何禁用获取请求的CORS



我有一个简单的web应用程序,我想在WinUI应用程序中运行,它可以获取外部HTML内容:

private async fetchHtml() {
const url = document.querySelector<HTMLInputElement>("#txt-url")!.value;
const html = await fetch(url).then(r => r.text());
document.querySelector<HTMLTextAreaElement>("#txt-html")!.value = html;
}

显然,这会导致CORS错误。我想禁用它,但找不到WinUI3:的任何方法

WinUI中的WebView2没有占用CoreWebView2EnvironmentOptionsEnsureCoreWebView2Async重载,因此此答案没有帮助。
  • URL是外部URL,因此此答案建议的SetVirtualHostNameToFolderMapping也没有帮助。

  • 我尝试注入我自己的CORS头,但它在fetch上不起作用(WebResourceResponseReceived事件不仅在fetch请求上触发):

  • c.WebResourceResponseReceived += (_, e) =>
    {
    var origin = e.Request.Headers.FirstOrDefault(q => q.Key == "Origin").Value;
    if (!string.IsNullOrEmpty(origin))
    {
    e.Response.Headers.AppendHeader("Access-Control-Allow-Origin",
    new Uri(e.Request.Uri).GetLeftPart(UriPartial.Authority));
    e.Response.Headers.AppendHeader("Access-Control-Allow-Methods", "*");
    e.Response.Headers.AppendHeader("Access-Control-Allow-Headers", "*");
    }
    };
    

    因此,实际上您需要在WebResourceRequested事件中处理代理请求。WebResourceResponseReceived在浏览器处理请求后被触发。

    若要手动代理请求,您需要首先设置web资源请求筛选器。

    // CoreWebView2WebResourceContext.XmlHttpRequest is triggered
    // by fetches for some reason. This filter will listen for any URI.
    this.webView.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.XmlHttpRequest);
    

    然后,您可以像WebResourceResponseReceived一样设置侦听器

    this.webView.CoreWebView2.WebResourceRequested += this.CoreWebView2_WebResourceRequested;
    

    因此,要代理请求,您需要设置一个HttpClient并手动处理请求。

    例如,这将代理所有请求,假设httpClient被定义为HttpClient:

    private void CoreWebView2_WebResourceRequested(object sender, CoreWebView2WebResourceRequestedEventArgs e)
    {
    HttpRequestMessage request = new(new HttpMethod(e.Request.Method), e.Request.Uri)
    {
    Content = new StreamContent(e.Request.Content)
    };
    foreach (KeyValuePair<string, string> header in e.Request.Headers)
    {
    // Copy base headers
    request.Headers.TryAddWithoutValidation(header.Key, header.Value);
    // Copy content headers
    request.Content.Headers.TryAddWithoutValidation(header.Key, header.Value);
    }
    // Make the request
    HttpResponseMessage response = httpClient.Send(request);
    // Custom headers
    response.Headers.Add("Access-Control-Allow-Origin", "*");
    // Webview2 Response expecting headers in a string with following format:
    //   key: value
    //   header2: value
    List<string> headers = response.Headers.Select(h => $"{h.Key}: {string.Join(",", h.Value)}").ToList();
    // Create Webview2 response
    CoreWebView2WebResourceResponse webView2WebResourceResponse = this.webView.CoreWebView2.Environment.CreateWebResourceResponse(
    response.Content.ReadAsStream(),
    (int)response.StatusCode,
    response.ReasonPhrase,
    string.Join('n', headers));
    e.Response = webView2WebResourceResponse;
    }
    

    注意

    构建响应对象时不应使用async方法。COM层不尊重线程。

    最新更新