Javascript 为什么在';中获取资源时主体解析器会失败;无cors';模式
我从文件系统打开一个静态页面,该页面试图从运行在localhost上的服务器(即目录列表/)获取资源。浏览器拒绝转发此请求,并建议:Javascript 为什么在';中获取资源时主体解析器会失败;无cors';模式,javascript,cross-domain,fetch,body-parser,Javascript,Cross Domain,Fetch,Body Parser,我从文件系统打开一个静态页面,该页面试图从运行在localhost上的服务器(即目录列表/)获取资源。浏览器拒绝转发此请求,并建议: 如果不透明响应满足您的需要,请将请求的模式设置为“无cors”,以获取禁用cors的资源。 然后我使用“无cors”提交请求: let body=JSON.stringify({action:"listfiles",path:"/"}) let headers = new Headers() headers.append("Content-Type", "app
如果不透明响应满足您的需要,请将请求的模式设置为“无cors”,以获取禁用cors的资源。
然后我使用“无cors”提交请求:
let body=JSON.stringify({action:"listfiles",path:"/"})
let headers = new Headers()
headers.append("Content-Type", "application/json");
fetch('http://localhost:9000/ajax',{
method: 'POST',
headers: headers,
body: body,
mode: 'no-cors'
}).then(
response=>response.json()
).then(
data=>this.onload(data)
)
在服务器端,我以以下方式使用express:
app.use('/ajax',bodyParser.json())
app.post("/ajax",function(req,res){
let action=req.body.action
console.log(`ajax ${action}`)
}
这一次,浏览器允许请求通过,甚至
app.post
也会获得请求,只是请求正文没有正确解析,而不是'listfiles'
我得到操作的未定义的值。(如果从本地主机加载页面,则不会出现相同的问题)。因为您正在尝试进行跨源调用(协议文件:
与协议http:
不同)。同源协议由浏览器实施,因此服务器看到请求也就不足为奇了。请求不包含允许浏览器对代码做出响应的CORS头,因此它不包含;您已经禁用了CORS。来自:
“跨源资源共享标准的工作原理是添加新的HTTP头,允许服务器描述允许使用web浏览器读取该信息的源集。此外,对于可能对服务器数据产生副作用的HTTP请求方法(特别是对于GET以外的HTTP方法,或对于某些MIME类型的POST使用),规范要求浏览器“预飞”请求,使用HTTP选项请求方法从服务器请求支持的方法,然后在服务器“批准”后,使用实际HTTP请求方法发送实际请求。”
我的请求的问题是它不符合简单的条件。这是因为它包含内容类型:application/json
头,以便主体解析器中间件将文档主体解析为json。因此它会触发飞行前请求
“简单的请求
有些请求不会触发CORS预飞。在本文中,这些请求称为“简单请求”,尽管Fetch规范(定义CORS)没有使用该术语。不触发CORS预飞的请求(即所谓的“简单请求”)满足以下所有条件:“…”
此处列出的条件包括对方法的限制、可设置的标题等。有关详细信息,请查看文档
虽然在简单请求中允许使用我使用的方法(POST
),并且在简单请求中也允许设置Content-Type
头,但Content-Type的唯一可能值是
application/x-www-form-urlencoded
multipart/form-data
text/plain
一个简单的请求
因为我的服务器不知道飞行前的请求,所以它不能正确处理我的请求是很自然的
另请参阅对答案的注释,即需要在客户端和服务器端传递哪些附加头才能使请求按预期工作。我认为我的问题是我的请求触发了预飞行。我的请求包含一个“application/json”内容类型头,以便主体解析器从中解析json。只需简单的GET、 HEAD,POST请求如果只包含允许的头,特别是内容类型头(其本身是允许的头),则不会触发预飞行允许的值为application/x-www-form-urlencoded、multipart/form data和text/plain,以使请求符合简单条件。@sbtpr:否,即使它没有触发预飞行,您仍需要在实际POST响应上设置相关的标题。(如果有预飞行,它们必须在两个响应上。如果没有,就只有GET/POST/HEAD响应。)请注意;请求不简单并不是没有CORS它不能工作的唯一原因。好的,我现在明白了。一旦我真的可以将请求转发到服务器,我仍然需要额外的头。我相信在请求中这就是来源(Referer?)和响应中的Access-Control-Allow-Origin.Yes。(Origin,not Referer。)您可能还需要至少Access-Control-Allow-Headers
。请参阅和。您基本上不想使用“mode:'no-cors'”。它告诉浏览器完全阻止前端JavaScript访问响应正文和标题。