fetch() 输入意外结束
Posted
技术标签:
【中文标题】fetch() 输入意外结束【英文标题】:fetch() unexpected end of input 【发布时间】:2018-01-23 14:51:43 【问题描述】:我正在使用 fetch() 从 api 服务器获取数据。我的错误如下所示:
Uncaught (in promise) SyntaxError: Unexpected end of input at
fetch.then.blob.
你能告诉我我做错了什么吗?
const weatherAPi ='https://www.metaweather.com/api/location/523920';
fetch(weatherAPi,
mode: 'no-cors'
).then(blob => blob.json())
.then(data => console.log(data))
【问题讨论】:
我只在浏览器控制台中测试时看到这个错误 问题是你得到的响应不是一个有效的json(看起来是null
)
多么轻率的安全措施。如果我想以不良行为者的身份获取公共托管的 JSON,使用其他方法很容易。如果我想把它当成一个好演员,那是不可能的。
这能回答你的问题吗? Handle response - SyntaxError: Unexpected end of input when using mode: 'no-cors'
【参考方案1】:
不透明的响应
对跨域资源的no-cors
请求的响应具有response type of 'opaque'。如果您在尝试将其转换为 JSON 之前记录响应,您将看到一种“不透明”类型。
不透明类型是 listed as "severely restricted",如 whatwg.org 上的获取规范中所述。
不透明过滤响应是过滤后的响应,其类型为“不透明”,url列表为空列表,状态为0,状态消息为空字节序列,头列表为空,正文为空,拖尾为空.
如Google's docs on the opaque type 所述,当类型不透明时,当前无法读取它们。
不透明响应是针对不返回 CORS 标头的不同来源的资源发出的请求。对于不透明的响应,我们将无法读取返回的数据或查看请求的状态,这意味着我们无法检查请求是否成功。使用当前的 fetch() 实现,不可能从窗口全局范围请求不同来源的资源。
在您的服务器上启用 CORS 支持
这可以取决于环境或语言。例如,您可以通过更改服务器配置来更改 nginx 环境中的 CORS 设置,或者您可以在应用程序代码(例如 php)中指定标头。
我强烈推荐阅读Mozilla documentation on CORS requests 和Access-Control-Allow-Origin。
PHP 中的一个例子:
<?php
header("Access-Control-Allow-Origin: *"); // "*" could also be a site such as http://www.example.com
【讨论】:
解决方案是什么...如果我删除no-cors
那么它会抛出跨域错误
@AnthonyWinzlet,您需要更新您尝试从中请求信息的服务器上的 CORS 标头。这些 CORS 策略是出于安全目的而制定的。这是一个相当长的阅读,但这是一个很棒的resource on CORS requests。
通常,当服务器抛出错误并且CORS与它无关时,您会得到一个CORS错误。因此,如果我知道我的 CORS 设置是正确的,我总是会开始检查服务器端代码是否存在问题。【参考方案2】:
我遇到了同样的问题。就我而言,这不是由解决方案指出的“不透明”响应类型引起的。 此代码导致空响应错误,因为 'fetch' 不接受带有空正文的响应:
return fetch(urlToUser, parameters)
.then(response =>
return response.json()
)
.then((data) =>
resolve(data)
)
.catch((error) =>
reject(error)
)
相反,在我的情况下效果更好:
return fetch(urlToUser, parameters)
.then(response =>
return response.text()
)
.then((data) =>
resolve(data ? JSON.parse(data) : )
)
.catch((error) =>
reject(error)
)
即使正文为空,获取文本也不会出现错误。然后检查数据是否存在并解决。 我希望它有所帮助:-)
【讨论】:
Github 的 fetch polyfill 团队也推荐了相同的解决方案:github.com/github/fetch/issues/268#issuecomment-176544728response.text()
对我来说是空的
我喜欢这个解决方案。我遇到了同样的问题,我的一些 REST 响应没有正文,而核心服务需要 JSON。这已经很好地解决了它!谢谢。【参考方案3】:
很多很好的回应,但我选择了这个:
const response = await fetch(url,
method: 'GET',
headers:
Authorization: 'Bearer ' + accessToken
);
const string = await response.text();
const json = string === "" ? : JSON.parse(string);
return json;
【讨论】:
撞!这个是赢家!【参考方案4】:您需要在 php 或其他服务器端点的标头中包含该行:
<?php
header('Access-Control-Allow-Origin: *');
//or
header('Access-Control-Allow-Origin: http://example.com');
// Reading JSON POST using PHP
$json = file_get_contents('php://input');
$jsonObj = json_decode($json);
// Use $jsonObj
print_r($jsonObj->message);
...
// End php
?>
使用 POST 请求获取代码的模型是:
const data =
optPost: 'myAPI',
message: 'We make a research of fetch'
;
const endpoint = 'http://example.com/php/phpGetPost.php';
fetch(endpoint,
method: 'POST',
body: JSON.stringify(data)
)
.then((resp) => resp.json())
.then(function(response)
console.info('fetch()', response);
return response;
);
【讨论】:
您也可以使用在线 cors 代理cors-anywhere.herokuapp.com 来规避这个问题,而无需自己编写 PHP。【参考方案5】:您遇到了 CORS 源策略问题。要解决这个问题,您需要访问服务器端 API 的权限。特别是,你需要在 php 或另一个服务器端点的 header 中添加一行:
<?php
header('Access-Control-Allow-Origin: *');
//or
header('Access-Control-Allow-Origin: http://example.com');
// Reading JSON POST using PHP
$json = file_get_contents('php://input');
$jsonObj = json_decode($json);
// Use $jsonObj
print_r($jsonObj->message);
...
// End php
?>
另外,请确保不要在服务器端点的标头中包含:
header("Access-Control-Allow-Credentials" : true);
使用 POST 请求获取代码的模型是:
const data =
optPost: 'myAPI',
message: 'We make a research of fetch'
;
const endpoint = 'http://example.com/php/phpGetPost.php';
fetch(endpoint,
method: 'POST',
body: JSON.stringify(data)
)
.then((resp) => resp.json())
.then(function(response)
console.info('fetch()', response);
return response;
);
【讨论】:
未捕获(承诺中)SyntaxError:JSON 输入意外结束 这与我的代码相同,但没有用...从***复制,代码说“嘿!这不是你的,这次我会做:D” -_ -【参考方案6】:(对于稍后来但正在处理“JSON 输入意外结束”这个问题的人)
很多时候的问题是服务器错误或只是无效的 URL 但您看不到它,因为互联网上所有如何使用 fetch
的示例都缺少一个重要部分 - 服务器或网络故障。
处理fetch
的正确方法是在转换为json
之前测试响应是否包含错误。
在测试resp.ok
的示例中检查第一个then
的部分:
async function fetchData()
return await fetch('https://your-server.com/some-NOt-existing-url/')
.then(resp =>
if (!resp.ok)
throw `Server error: [$resp.status] [$resp.statusText] [$resp.url]`;
return resp.json();
)
.then(receivedJson =>
// your code with json here...
)
.catch(err =>
console.debug("Error in fetch", err);
setErrors(err)
);
【讨论】:
【参考方案7】:输入意外结束
// .then((response) => response.json()) . // commit out this part
https://github.com/github/fetch/issues/268
fetch(url,
method: 'POST',
body: JSON.stringify(requestPayload),
headers:
'Content-type': 'application/json; charset=UTF-8',
Authorization: 'Bearer ' + token,
,
)
// .then((response) => response.json()) . // commit out this part
.then((json) =>
console.log("response :- ", json);
getCheckedInTrailersList();
).catch((error)=>
console.log("Api call error ", error.message);
alert(error.message);
);
【讨论】:
以上是关于fetch() 输入意外结束的主要内容,如果未能解决你的问题,请参考以下文章
FormatException:输入意外结束(在字符 1 处)