尝试从客户端的 Medium API 访问公共故事时出错
Posted
技术标签:
【中文标题】尝试从客户端的 Medium API 访问公共故事时出错【英文标题】:Error while trying to access public stories from Medium API on client side 【发布时间】:2018-05-25 08:17:26 【问题描述】:我正在尝试访问 Medium 的 API 以获取用户的公开故事列表。但是,当我尝试在客户端访问它时出现 CORS 错误。这是代码
axios.get(`http://medium.com/@ev/latest`).then((res)=>
console.log(res.data)
)
.catch((error)=>
console.log(error)
)
我做了一些研究,发现了这个github issue,但找不到任何解决方法。有没有办法让这个请求在客户端工作?
【问题讨论】:
【参考方案1】:使用此Medium API,您可以轻松获取特定用户编写的article_ids
列表(使用他们的user_id
)。
使用端点GET /user/user_id/articles。
它将返回一个 JSON 响应,如下所示:
"associated_articles": [
"*hash_id_of_article_1*",
"*hash_id_of_article_2*",
"*hash_id_of_article_3*",
.
.
.
]
然后,您可以使用此article_ids
列表来获取单个文章的信息或内容。像这样:
注意:article_id
指的是与每个 Medium Story/Article 相关联的唯一哈希 id。您可以在帖子 URL 的末尾看到它。
基本网址: https://medium2.p.rapidapi.com
GET /article/article_id
此端点将返回与文章相关的信息,例如标题、副标题、拍手、投票者、标签、主题、作者(user_id)、发布日期等……
"id": "*article_id*",
"title": "*article_title*",
"subtitle": "*article_subtitle*",
"claps": "*claps_count*",
"voters": "*voters_count*",
"published_at": "*date_of_publishing*",
"word_count": "*word_count*"
.
.
.
GET /article/article_id/content
此端点将返回文章的文本内容。
"content": "This is the article's textual content. Blah, blah, blah ..."
更详细的解释可以查看这个页面:https://medium.com/p/fcdb1576558a
文档:https://nishu-jain.medium.com/medium-apis-documentation-3384e2d08667
用于测试 api:https://rapidapi.com/nishujain1997.19@gmail.com/api/medium2/
【讨论】:
【参考方案2】:您可以通过 CORS 代理发出请求,从 https://medium.com/@ev/latest 获取 html,可以是您自己设置的代理,也可以使用像 https://cors-anywhere.herokuapp.com/ 这样的公共开放 CORS 代理。以下是使用标准 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' 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
会失败。
这就是为什么这个答案中的第一个 sn-p 使用 Fetch API 代替(你可以用它取回文本)。
【讨论】:
【参考方案3】:Medium 目前不允许这样做(服务器没有响应 Access-Control-Allow-Origin
标头)。可能是出于安全考虑。
正如您链接到的 GitHub 问题中所建议的,一种可能的解决方案是通过您的服务器(作为代理)将请求传送到 Medium。您可以在您的服务器(即http://my-server.com/get-medium/@ev/latest
)上创建一个端点,该端点将检索请求的媒体页面(在服务器端)并将其返回给客户端。
此问题的评论描述了一种使用 AWS Lambda 作为代理服务器的方法 - link
【讨论】:
以上是关于尝试从客户端的 Medium API 访问公共故事时出错的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 API 网关配置对 eureka 客户端的 API 请求
如何使用从公共客户端发出的令牌查询 keycloak 资源权限