尝试从客户端访问 API 中的 public 个故事时出错

Error while trying to access public stories from Medium API on client side

我正在尝试访问 Medium 的 API 以获取用户的 public 故事列表。但是,当我尝试在客户端访问它时出现 CORS 错误。这是代码

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

我做了一些研究并发现了这个 github issue,但找不到任何解决方法。有什么方法可以让这个请求在客户端工作吗?

Medium 目前不允许这样做(那里的服务器不响应 Access-Control-Allow-Origin header)。可能是出于安全考虑。

正如您链接到的 GitHub 问题中所建议的那样,一个可能的解决方案是通过您的服务器(作为代理)将请求传送到 Medium。您可以在您的服务器上创建一个端点(即 http://my-server.com/get-medium/@ev/latest),它将检索请求的媒体页面(在服务器端)并将 return 它发送到客户端。

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

您可以从 https://medium.com/@ev/latest by making your request through a CORS proxy — either a proxy you set up yourself or else just by using a public open CORS proxy like https://cors-anywhere.herokuapp.com/ 获得 HTML。以下是使用标准 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”问题.

的答案中

顺便说一句,如果你想要 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:

The JSON page is not intended to be used as a read API. The extra code is there to support our own use and is a standard technique to avoid JSON hijacking.

虽然解决这个问题很简单:只需首先在客户端代码中将响应作为文本处理,然后从开头删除 ])}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:

This is because JSON.parse is always tried in the response, even if responseType is text. We should fix that indeed.

https://medium.com/@ev/latest 是 HTML,而不是 JSON,因此 运行ning JSON.parse 将失败。

这就是为什么此答案中的第一个片段使用 Fetch API 代替(您可以用它取回文本)。