Angular2 Yelp API CORS 错误

Angular2 Yelp API CORS error

在实施 V3 API 时,我的 Ionic2/Angular2 应用程序遇到以下 CORS 问题:

XMLHttpRequest 无法加载 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' 因此不允许访问。响应具有 HTTP 状态代码 404。

在使用 API 的 V2 时,我 "bypassing" 使用 http.jsonp whish 的 CORS 问题不再适用,因为应该在 header的GET请求(据我了解,一个Jsonpheader不能修改)。

这就是我尝试的原因

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);
            });
    });
}

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);
    });
}

并且两种解决方案都不成功,也就是两种解决方案都导致了上面列出的 CORS 错误。

我是不是遗漏了什么或者我如何从 Ionic2 / Angular2 查询 Yelp API v3?

谢谢 最好的问候

P.S.: 请注意,我的 OAuth access_token 没有公开。身份验证由我的后端生成。

更新

在@Thierry Templier 回答后我找到了一个适用于 Ionic2 的解决方案。

在浏览器中调试时,我使用代理查询Yelp API V3。因此,我添加 ionic.config.json 文件

 "proxies": [{
    "path": "/yelp/v3/businesses",
    "proxyUrl": "https://api.yelp.com/v3/businesses"
 }]

并执行如下查询

this.http.get('http://localhost:8100/yelp/v3/businesses/' + 'search', ...

请注意,以下内容也有效

this.http.get('/yelp/v3/businesses' + 'search', ...

当 iOS 和 Android 中的 运行 时,代理不应该使用,也不会工作。因此,我在服务中执行如下查询

this.http.get('https://api.yelp.com/v3/businesses/search, ...

当然,为了方便使用,我编写了一个 gulp 任务,允许我在环境之间切换。

但是,这个方案只适用于Ionic2。如果我必须在网站的 Angular2 中实现它,我也需要猜测一个代理,但不确定。因此,我在 Yelp API V3

的问题列表中打开了该任务的副本

https://github.com/Yelp/yelp-api-v3/issues/21

问题不在客户端,因为浏览器会透明地处理跨域请求。它将在后台发送 Origin header。服务器必须按照以下方式处理 CORS:

  • 在响应中发回 CORS headers 以启用(或禁用)此类请求。
  • 必要时处理预检请求。

有关详细信息,请参阅本文:

我查看了 v3 版本的文档,没有看到任何关于 CORS 或 JSONP 的内容。唯一剩下的解决方案是在您的服务器应用程序中实施代理作为变通方法。我知道这并不理想,但这是我看到的唯一可能的解决方案