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-176544728 response.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() 输入意外结束的主要内容,如果未能解决你的问题,请参考以下文章

JSON解析错误语法错误意外结束输入

JSON.parse()返回输入的意外结束

FormatException:输入意外结束(在字符 1 处)

apollo graphql 突变 - JSON 输入意外结束

Next.js 中的 JSON 输入意外结束

Golang json Unmarshal “JSON 输入意外结束”