我正在尝试访问 Medium 的 API 以获取用户的公共故事列表。但是,当我尝试在客户端访问它时出现 CORS 错误。这是代码
axios.get(`http://medium.com/@ev/latest`).then((res)=>{
console.log(res.data)
})
.catch((error)=>{
console.log(error)
})
我做了一些研究,发现了这个github 问题,但找不到任何解决方法。有没有办法让这个请求在客户端工作?
我正在尝试访问 Medium 的 API 以获取用户的公共故事列表。但是,当我尝试在客户端访问它时出现 CORS 错误。这是代码
axios.get(`http://medium.com/@ev/latest`).then((res)=>{
console.log(res.data)
})
.catch((error)=>{
console.log(error)
})
我做了一些研究,发现了这个github 问题,但找不到任何解决方法。有没有办法让这个请求在客户端工作?
您可以从https://medium.com/@ev/latest获取 HTML,方法是通过 CORS 代理(您自己设置的代理或仅使用https://cors等公共开放 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”问题,答案是No 'Access -Control-Allow-Origin' 标头出现在请求的资源上 - 当尝试从 REST API 获取数据时。
顺便说一句,如果你想要 JSON,你可以尝试https://medium.com/@ev/latest?format=json但你会发现你得到的实际上不是有效的 JSON;相反,它开始是这样的:
])}while(1);</x>{"success":true,"payload":{"user":{"userId":"268314bb7e7e","name"…
显然这是故意的,根据 Medium 开发人员在其问题跟踪器中的评论:
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 显然仍然尝试将响应解析为 JSON:
这是因为
JSON.parse
总是在响应中尝试,即使responseType
是文本。我们确实应该解决这个问题。
而且https://medium.com/@ev/latest是 HTML,不是 JSON,所以JSON.parse
在上面运行会失败。
这就是为什么这个答案中的第一个片段使用 Fetch API 代替(你可以用它取回文本)。
目前,Medium 不允许这样做(服务器不响应Access-Control-Allow-Origin
标头)。可能是出于安全考虑。
正如您链接到的 GitHub 问题中所建议的那样,一个可能的解决方案是通过您的服务器(作为代理)将请求隧道传输到 Medium。您可以在您的服务器(即http://my-server.com/get-medium/@ev/latest
)上创建一个端点,该端点将检索请求的媒体页面(在服务器端)并将其返回给客户端。
此问题的评论描述了一种使用 AWS Lambda 作为代理服务器的方法 -链接