首页 > 解决方案 > 为什么 curl 在收到早期响应时会提前终止对我的服务器的 http 请求,但来自我的浏览器前端的 http 请求却没有?

问题描述

我的 API 服务器中有一个接受文件上传的 https 路由。对上传有一些验证,例如,如果查询参数之一无效,则服务器会在使用整个请求正文(可能非常大)之前拒绝上传。

当我使用 curl(或来自 Insomnia,我认为它只是在后台使用 curl)对该 API 运行请求时,并且服务器在消耗整个主体之前返回响应时,curl 终止而不继续上传数据,即使它没有继续上传数据发送了整个有效载荷。

卷曲命令:

curl --request POST \
  --url 'https://api.example.com/v0/projects/38/media?filename=somethingInvalid' \
  --header 'content-type: video/mp4' \
  --cookie session=orMaybeIAmInvalid \
  --data '<gigantic chunk of binary here>'

这在一秒钟内终止,服务器返回 400 并带有一些响应,例如your stuff is wrong yo. 但是,如果查询参数有效,则上传大约需要 5 分钟。所以这一切都按预期工作:我不想让用户等待几分钟和几分钟的 400 根本不基于文件的内容。

相同的请求与我的前端 Web 应用程序具有相反的行为。如果我使用相同的配置运行 xmlhttprequest 请求,即使 Web 服务器已达到尝试返回 400 并且不再关心正在上传的请求正文的程度,浏览器也会在解析之前持续运行 5 分钟它已收到 400。这是为什么呢?

我说“它试图在哪里返回 400”,因为我不确定底层技术是如何在这里工作的。我有,在我的内置游戏框架的网络服务器中,这条线只是返回 400:

if (stuff.isInvalid()) {
  return completedFuture(badRequest("your stuff is wrong yo"));
}

但是,想想看,考虑到此时请求正文还没有被完全消耗掉,我真的很惊讶这对 curl 完全有效。因此,尽管我在问“为什么这个浏览器请求不按我想要的方式工作”,但我也在问我需要做哪些特定的研究途径来了解这里发生了什么。

标签: javascriptcurlhttpsplayframeworkxmlhttprequest

解决方案


听起来像是curl在发送请求的同时检查响应,并且在完成发送请求之前注意到响应已经发生。这不是正常的网络服务器行为,显然它将其视为不需要完成请求的意思。

浏览器的逻辑不同,它直到完成发送整个请求后才开始从网络读取。

当查询参数有效时,应等到post数据全部接收完毕后再发送响应,然后curl才不会终止请求。这仍然允许您异步完成处理。


推荐阅读