如何从浏览器控制台获取 localhost 资源而不出现违反内容安全策略的错误?

How can I fetch a localhost resource from the browser console and not get the Content Security Policy violation error?

我有最简单的本地 http 服务器,它连接到本地主机提供单个文件。我可以很好地从浏览器导航到资源,但我需要能够从浏览器控制台使用 fetch 网络 api 获取资源,但这不起作用 除非控制台来自完全相同的来源.

请注意:

资源已上线:

C:\> (Invoke-WebRequest http://localhost:49152/C:/temp/events/62.0.0.32712-0515-834-4.build.Main_events.json).StatusCode
200
C:\>

控制台同源时:

否则:

我知道我可以忽略第一个错误 - 提到 http://127.0.0.1:9001 的错误。所以我的问题是第二个错误:

Refused to connect to 'http://localhost:49152/C:/temp/events/62.0.0.32712-0515-834-4.build.Main_events.json' because it violates the document's Content Security Policy.

到目前为止我还没有弄清楚如何修复它。这似乎是经典的 CORS 问题,但是当 运行 fetch 时,浏览器不会发出任何预检 OPTIONS 请求。我知道这一点,因为我是 运行 Fiddler。它显示来自同一来源的 GET 请求,但绝对没有来自其他来源的请求。

我尝试使用的原始 fetch 代码是这样的:

    const request = fetch(url)
                        .then(response => response.blob())
                        .then(blob => {
                          globals.dispatch(Actions.openTraceFromFile({
                            file: new File([blob], fileName),
                          }));
                        })
                        .catch(e => alert(`Could not load local trace ${e}`));

它来自 https://www.ui.perfetto.dev/,我试图以非交互方式加载我的跟踪文件。

(此问题与 and 有关)

我尝试 运行 chrome 使用 --disable-web-security 标志,这应该禁用 CORS 验证(据我对这个标志的最佳理解)。无果。

我能做些什么来让它发挥作用吗?


网络服务器源代码:

function NavigateToFile(
    [Parameter(Mandatory)][ValidateScript({ Test-Path $_ -PathType Leaf })]$FilePath,
    [scriptblock]$Action
)
{
    $port = Get-OpenTcpPort
    $http = [Net.HttpListener]::new()
    $http.Prefixes.Add("http://localhost:$Port/")
    $http.Start()

    $FilePath = (Get-Item $FilePath).FullName.Replace('\', '/')
    $ExpectedUrl = "$($http.Prefixes)$FilePath"
    $ExpectedUrl | ForEach-Object $Action

    try
    {
        $run = $true
        while ($http.IsListening -and $run)
        {
            $context = $http.GetContext()
            Write-Host "$($context.Request.HttpMethod) $($context.Request.Url)"
            if ($context.Request.HttpMethod -eq 'GET')
            {
                if ($context.Request.Url -eq $ExpectedUrl)
                {
                    $buffer = [IO.File]::ReadAllBytes($FilePath)
                }
                else
                {
                    $buffer = [Text.Encoding]::UTF8.GetBytes("Terminated")
                    $run = $false
                }
                $context.Response.ContentLength64 = $buffer.Length
                $context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
                $context.Response.OutputStream.Close()
            }
        } 
    }
    finally
    {
        $http.Close();
    }
}

这不是 CORS,它是内容安全策略,在此处定义:

https://github.com/google/perfetto/blob/master/ui/src/frontend/index.ts#L127

它仅支持从 localhost:9001 获取以减少攻击面。

如果您让网络服务器侦听端口 9001 而不是随机端口,错误应该会消失。