Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么在';中获取资源时主体解析器会失败;无cors';模式_Javascript_Cross Domain_Fetch_Body Parser - Fatal编程技术网

Javascript 为什么在';中获取资源时主体解析器会失败;无cors';模式

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

我从文件系统打开一个静态页面,该页面试图从运行在localhost上的服务器(即目录列表/)获取资源。浏览器拒绝转发此请求,并建议:

如果不透明响应满足您的需要,请将请求的模式设置为“无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访问响应正文和标题。