问题
While implementing the V3 API I face the following CORS problem with my Ionic2/Angular2 application:
XMLHttpRequest cannot load https://api.yelp.com/v3/businesses/search. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 404.
While using the V2 of the API, I was "bypassing" the CORS problem using http.jsonp whish isn't applicable anymore, because the authorization bearer should be added in the header of the GET request (as far as I understood, a Jsonp header can't be modified).
That's why I tried
private queryYelp(yelpOAuth:YelpCommunication.YelpOAuthSignature, nextTo:AddressLocation.Location):Promise<{}> {
let params:URLSearchParams = new URLSearchParams();
params.set('limit', '' + Resources.Constants.Default.YELP.LIMIT);
params.set('latitude', '' + nextTo.coordinates[0]);
params.set('longitude', '' + nextTo.coordinates[1]);
params.set('radius', '' + Resources.Constants.Default.YELP.RADIUS);
params.set('sort_by', Resources.Constants.Default.YELP.SORT.BEST_MATCHED);
let headers:Headers = new Headers();
headers.append('Authorization', 'Bearer ' + yelpOAuth.access_token);
let options:RequestOptions = new RequestOptions({
headers: headers,
search: params,
withCredentials: true
});
return new Promise((resolve, reject) => {
this.http.get(Resources.Constants.Default.YELP.URL, options)
.map(res => res.json())
.subscribe((businesses:Yelp.YelpBusiness[]) => {
resolve(businesses);
}, (errorResponse:Response) => {
reject(errorResponse);
});
});
}
or
private queryYelp(yelpOAuth:YelpCommunication.YelpOAuthSignature, nextTo:AddressLocation.Location):Promise<{}> {
return new Promise((resolve, reject) => {
let xhr:XMLHttpRequest = new XMLHttpRequest();
let formData:FormData = new FormData();
formData.append('limit', '' + Resources.Constants.Default.YELP.LIMIT);
formData.append('latitude', '' + nextTo.coordinates[0]);
formData.append('longitude', '' + nextTo.coordinates[1]);
formData.append('radius', '' + Resources.Constants.Default.YELP.RADIUS);
formData.append('sort_by', Resources.Constants.Default.YELP.SORT.BEST_MATCHED);
xhr.onload = () => {
console.log("status " + xhr.status);
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status == 201) {
let businesses:Yelp.YelpBusiness[] = JSON.parse(xhr.responseText);
resolve(businesses);
} else {
reject();
}
};
xhr.onerror = () => {
alert('Woops, there was an error making the request.');
};
xhr.open("GET", Resources.Constants.Default.YELP.URL, true);
xhr.setRequestHeader("Authorization", 'Bearer ' + yelpOAuth.access_token);
xhr.send(formData);
});
}
and both solution weren't successful aka both solution leaded to the CORS error listed above.
Did I miss something or how could I query the Yelp API v3 from Ionic2 / Angular2?
Thx Best regards
P.S.: Note that my OAuth access_token isn't exposed. The authentication is generated by my backend.
UPDATE
After @Thierry Templier answer I found a solution which works for Ionic2.
When debugging in the browser, I query the Yelp API V3 using a proxy. Therefor I add in ionic.config.json file
"proxies": [{
"path": "/yelp/v3/businesses",
"proxyUrl": "https://api.yelp.com/v3/businesses"
}]
and do the query like following
this.http.get('http://localhost:8100/yelp/v3/businesses/' + 'search', ...
note that following would also work
this.http.get('/yelp/v3/businesses' + 'search', ...
When running in iOS and Android, the proxy should not be use aka not gonna work. Therefor I do the query like following in my service
this.http.get('https://api.yelp.com/v3/businesses/search, ...
Of course, to have something handy, I write a gulp task which allow me to switch between environments.
But, this solution is only applicable for Ionic2. If I would have to implement it in Angular2 in a website, I would need I guess a proxy too, not sure about it. Therefor I opened a copy of that task in the issues list of the Yelp API V3
https://github.com/Yelp/yelp-api-v3/issues/21
回答1:
The problem isn't on the client side since the browser will transparently Hamble cross domain requests. It will send under the hood the Origin
header. The server must handle CORS following this:
- Send the CORS headers back in the response to enable (or not) such kind of requests.
- Handle preflighted requests if necessary.
See this article for more details:
- http://restlet.com/blog/2015/12/15/understanding-and-using-cors/
I had a look at the docs of the v3 version and can see nothing regarding CORS or JSONP. The only remaining solution is to implement a proxy in your server application as a workaround. I'm aware that it's not ideal but it's the only possible solution I see
来源:https://stackoverflow.com/questions/38598928/angular2-yelp-api-cors-error