尝试从客户端的Medium API访问公共故事时出错

时间:2017-12-11 18:33:45

标签: cors cross-browser axios medium.com

我尝试访问中型API以获取用户的公开报道列表。但是,当我尝试在客户端访问它时,我收到了CORS错误。这是代码

axios.get(`http://medium.com/@ev/latest`).then((res)=>{
  console.log(res.data)
})
.catch((error)=>{
  console.log(error)
})

我做了一些研究并找到了github issue,但找不到任何解决方法。有没有办法让这个请求在客户端工作?

2 个答案:

答案 0 :(得分:2)

您可以通过CORS代理发出请求来获取https://medium.com/@ev/latest中的HTML - 您自己设置的代理,或者只使用公共开放式CORS代理https://cors-anywhere.herokuapp.com/。以下是使用标准Fetch API的方法:

fetch("https://cors-anywhere.herokuapp.com/https://medium.com/@ev/latest")
  .then(res => res.text())
  .then(text => document.querySelector("div").innerHTML = text)
  .catch(error => console.log(error))
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div></div>

有关更多详细信息 - 包括如何在几分钟内在Heroku上设置自己的CORS代理,请参阅如何使用CORS代理来解决“No Access-Control-Allow-Origin header”问题< / em>在 No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API 的答案中。

顺便说一句,如果你想要JSON,你可以尝试https://medium.com/@ev/latest?format=json,但你会发现你得到的东西实际上并不是有效的JSON;相反,它开始像这样:

])}while(1);</x>{"success":true,"payload":{"user":{"userId":"268314bb7e7e","name"…

显然这是故意的,per a comment from a Medium developer in their issue tracker

  

JSON页面不能用作读取API。额外的代码用于支持我们自己的使用,是避免JSON劫持的标准技术。

然而,解决这个问题很简单:首先在客户端代码中将响应作为文本处理,然后从开头删除])}while(1);</x>,然后在剩下的内容上运行JSON.parse

但是就使用Axios获取文本响应而言,我认为即使您通过CORS代理发出请求,您也会发现它不会按预期工作;试试这个:

axios.get('https://cors-anywhere.herokuapp.com/http://medium.com/@ev/latest', {
    responseType: 'text'
  })
  .then(res => console.log(res.data))
  .catch(error => console.log("ERROR"))
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

代码点击catch,因为即使您指定responseType: 'text'Axios apparently still tries the parse the response as JSON

也是如此
  

这是因为即使JSON.parse是文字,也始终在回复中尝试responseType。我们应该确实这样做。

https://medium.com/@ev/latest是HTML,而不是JSON,因此在其上运行JSON.parse会失败。

这就是为什么这个答案中的第一个片段改为使用Fetch API(你可以用它来获取文本)。

答案 1 :(得分:0)

Medium目前不允许这样做(服务器不会使用Access-Control-Allow-Origin标头进行响应)。可能是出于安全考虑。

正如您链接的GitHub问题所示,可能的解决方案是通过您的服务器(作为代理)将请求隧道传输到Medium。您可以在服务器上创建一个端点(即http://my-server.com/get-medium/@ev/latest),该端点将检索所请求的中间页面(在服务器端)并将其返回给客户端。

此问题的评论描述了使用AWS Lambda作为代理服务器的方法 - link