【发布时间】:2019-08-13 04:04:51
【问题描述】:
我有一个用 Node.js 编写的服务器,以及一个在浏览器中运行的 Web 客户端。客户端应从服务器上传和下载一些文件。服务端不是最初下发客户端的,所以我们这里是跨域的情况。
服务器使用cors 中间件来启用跨域请求。由于我还使用了许多自定义标头,因此我将其与如下配置一起使用:
api.use(cors({
origin: '*',
allowedHeaders: [ 'content-type', 'authorization', 'x-metadata', 'x-to' ],
exposedHeaders: [ 'content-type', 'content-disposition', 'x-metadata' ]
}));
相比之下,客户端使用的是axios,上传文件的代码是这样的:
await axios({
method: 'post',
url: 'https://localhost:3000/api/v1/add-file',
data: content,
headers: {
// ...
}
});
到目前为止,一切都按预期工作,尤其适用于 CORS。
现在我想跟踪上传进度,因此我将onUploadProgress 回调添加到axios 调用中,如suggested by its documentation:
await axios({
method: 'post',
url: 'https://localhost:3000/api/v1/add-file',
data: content,
headers: {
// ...
},
onUploadProgress (progressEvent) {
console.log({ progressEvent });
}
});
如果我现在运行客户端,上传仍然有效 - 但永远不会调用 onUploadProgress 回调。我读过并非所有浏览器都支持这个(在内部这只是绑定到底层XmlHttpRequest对象的onprogress事件),但最新的Chrome应该能够做到这一点(如果我尝试不同的设置,CORS是不参与,一切似乎都有效)。所以我认为这是一个 CORS 问题。
我有read,一旦您向onprogress 事件添加侦听器,就会发送预检请求。这反过来意味着服务器必须接受OPTIONS 请求。为此,我在服务器上添加了以下代码,在上述对api.use的调用之前:
api.options('*', cors({
origin: '*',
methods: [ 'GET', 'POST' ],
allowedHeaders: [ 'content-type', 'authorization', 'x-metadata', 'x-to' ],
exposedHeaders: [ 'content-type', 'content-disposition', 'x-metadata' ],
optionsSuccessStatus: 200
}));
结果:上传仍然有效,但仍然没有引发 onUploadProgress 事件。所以我假设我遗漏了一些与 CORS 相关的东西。问题只是:我错过了什么?
我还尝试使用更大的文件(几乎 2 GBytes 而不是几个 KBytes)重新运行相同的设置,但结果是相同的。有谁知道我在这里做错了什么?
更新
回复部分cmets:首先,我的axios版本是0.18.0,所以我使用的是最新的稳定版本。
服务器的源代码可以在存储库thenativeweb/wolkenkit-depot 中找到。 CORS 部分配置为here。请注意,这与我上面发布的版本略有不同,因为我做了一些本地更改。但是,这是您需要处理的地方。
要构建服务器,您需要安装 Node.js 和 Docker。然后,运行:
$ npm install
$ npx roboter build
这将生成一个新的 Docker 映像,其中包含服务器的代码(您需要此 Docker 映像才能运行下面的客户端测试)。请注意,如果您更改服务器上的任何内容,则必须再次重建此 Docker 映像。
客户端可以在存储库thenativeweb/wolkenkit-depot-client-js,在分支issue-145-notifiy-about-progress-when-uploading-or-downloading-files中找到。
在文件DepotClient.js 中,我向onUploadProgress 添加了一个事件侦听器,它应该只是抛出一个异常(这反过来应该很明显地引发了事件)。
此代码随后由this test 运行(对此有更多测试,但这是其中之一),这应该会导致异常,但不会。
再次运行测试,您必须安装 Node.js 和 Docker,并且您必须按照前面所述构建服务器。然后使用以下命令代表您运行测试:
$ npm install
$ npx roboter test --type integration
我的期望是至少有一个addFile 测试应该提交。事实是,它们都变成绿色,这意味着上传本身可以完美运行,但从未引发 onUploadProgress 事件。以防万一您想知道执行测试的环境:我在这里使用的是 puppeteer,它是一个无头 Chrome。
【问题讨论】:
-
环境如何?它是在代理后面还是类似的东西?
-
两者都在本地主机上运行,只是端口不同。没有代理,没有防火墙,或其他任何东西......
-
你能提供你的路由的服务器端代码吗?因为我没有问题,所以我在项目中使用
onUploadProgress没有问题。还有你能指定你正在使用的 axios 的版本吗? -
我扩展了我的问题,并提供了指向源代码的链接以及有关如何构建事物的说明。由于有可用的测试,如果您遵循构建步骤,它应该很容易重现。同样,正如文中所述:在客户端运行测试之前构建服务器非常重要!而且,在服务器上每次更改后,您都需要重新构建!
-
您是否在客户端中看到任何对 OPTIONS 预检请求的响应?如果后端没有正确配置来处理 OPTIONS 请求,它将返回一个错误(可能是
Status Code: 405 Method Not Allowed)。
标签: javascript node.js cors xmlhttprequest axios