问题
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 ifresponseType
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