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

时间秒杀一切 提交于 2019-12-23 15:44:50

问题


I'm trying to access Medium's API to get a list of public stories from a user. However, I'm getting a CORS error when I try to access it on the client side. Here's the code

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

I did some research and found this github issue, but couldn't find any workaround. Is there any way to make this request work on the client side?


回答1:


You can get the HTML from 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/. Here’s how to do it using the standard 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>

For more details — including how to set up your own CORS proxy on Heroku in just a few minutes, see How to use a CORS proxy to get around “No Access-Control-Allow-Origin header” problems in the answer at No 'Access-Control-Allow-Origin' header is present on the requested resource—when trying to get data from a REST API.


Incidentally, if instead you want JSON, you can try https://medium.com/@ev/latest?format=json but you’ll find that what you get back isn’t actually valid JSON; instead it starts out like this:

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

Apparently that’s intentional, 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.

That’s trivial to work around, though: Just first handle the response as text in your client code, and strip out the ])}while(1);</x> from the start of it, and then run JSON.parse on what remains.

But as far as using Axios to get the response as text, I think you’ll find it’s not going to work as expected even if you make the request through a CORS proxy; try this:

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>

The code hits the catch because apparently even when you specify 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.

And https://medium.com/@ev/latest is HTML, not JSON, so running JSON.parse on it will fail.

That’s why the first snippet in this answer uses the Fetch API instead (you can get text back with it).




回答2:


This is currently not allowed by Medium (There server doesn't respond with the Access-Control-Allow-Origin header). Probably because of security concerns.

As suggested in the GitHub issue you linked to, a possible solution will be to tunnel the request to Medium through your server (as proxy). You can create an endpoint on your server (i.e. http://my-server.com/get-medium/@ev/latest) that will retrieve the requested Medium page (on the server side) and will return it to the client side.

This comment to the issue describes a way to do that using AWS Lambda as the proxy server - link



来源:https://stackoverflow.com/questions/47759184/error-while-trying-to-access-public-stories-from-medium-api-on-client-side

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!