【问题标题】:How to send an HTTP GET request using Firebase and Angular?如何使用 Firebase 和 Angular 发送 HTTP GET 请求?
【发布时间】:2018-02-04 12:17:21
【问题描述】:

我的应用程序使用 IBM Watson Speech-to-Text,这需要访问令牌。从命令行我可以使用 curl 获取访问令牌:

curl -X GET --user my-user-account:password \
--output token \
"https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api"

当我使用 Angular 的 $http 服务发出 HTTP 请求时,出现 CORS 错误:

var data = {
  user: 'my-user-account:password',
  output: 'token'
};

$http({
    method: 'GET',
    url: 'https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api',
    data: data,
}).then(function successCallback(response) {
  console.log("HTTP GET successful");
}, function errorCallback(response) {
  console.log("HTTP GET failed");
});

错误信息说:

请求中没有“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“http://127.0.0.1:8080” 使用权。响应的 HTTP 状态代码为 401。

据我了解,无法从 Angular 执行 CORS; CORS 必须从服务器完成。我知道如何使用 Node 进行 CORS,但我使用 Firebase 作为服务器。

Firebase 有 documentation 关于使用 CORS 发出 HTTP 请求的信息。文档说要这样写:

$scope.getIBMToken = functions.https.onRequest((req, res) => {
  cors(req, res, () => {

  });
});

首先,这是行不通的。错误消息是functions is not defined。显然 functions 不在 Firebase 库中?我从index.html 致电 Firebase:

<script src="https://www.gstatic.com/firebasejs/4.3.0/firebase.js"></script>

我的控制器为$firebaseArray$firebaseAuth$firebaseStorage 注入依赖项。我是否需要为 $firebaseHttp 或类似的东西注入依赖项?

二、如何指定方法('GET')、URL、数据(我的账号和密码)?

【问题讨论】:

  • 简短的回答是,令牌生成器端点不支持 CORS——也就是说,它不支持从浏览器中运行的前端 JavaScript 代码接收跨域请求——因此您可以调用它的唯一方法是:(A)改为从您的后端代码发出请求;或 (B) 使用来自 github.com/Rob--W/cors-anywhere 或类似的代码设置 CORS 代理,然后让您的前端代码通过该 CORS 代理发出请求
  • 由于该 API 需要身份验证,但显然需要您将这些凭据作为 GET 请求的一部分发送,因此您将 Authorization: Basic bXk… 请求标头添加到请求中,其中 bXk… 替换为account:password 形式的实际帐户名和密码的 Base64 编码 - 但如果您尝试这样做,您会发现它也会失败,再次出现 401。那是因为添加了 Authorization 标头请求触发浏览器首先自动执行 CORS 预检 OPTIONS 请求(在代码中尝试 GET 请求之前)并且预检失败。
  • CORS 预检失败的原因是,令牌生成器端点显然需要对 OPTIONS 请求进行身份验证(它不应该),但浏览器没有向其中添加 Authorization 标头预检OPTIONS 请求——因为预检的全部目的是询问服务器是否可以接收包含该标头的跨域请求。

标签: angularjs firebase cors httprequest ibm-watson


【解决方案1】:

答案是使用 Cloud Functions for Firebase,它支持从服务器运行节点功能。然后使用 Node 模块 request 从 Node 发送 HTTP 请求。

【讨论】:

    【解决方案2】:

    如果您想使用 Angular 发送凭据,只需设置 withCredentials=true。我也将 CORS 与 Angular v4 一起使用,对于您的 HTTP 标头错误,您是对的。标头Access-Control-Allow-Origin必须在服务器端添加,检查你的api中是否有允许某些域、url、页面的设置,因为google api有这个功能,所以检查你获取token的地方应该有一些设置。

    这里是示例,我如何使用打字稿通过 CORS 调用 API:

    broadcastPresense(clientId: string) {
        const headers = new Headers({'Content-Type':'application/json','withCredentials':'true'});
        return this.http.post('http://localhost/api.php',
        {
           'jsonrpc': '2.0',
           'method': 'somemethod',
           'params': {'client_id': clientId},
           'id': CommonClass.generateRandomString(16)
        },{headers: headers, withCredentials:true}).map(
            (res: Response) => {
               console.log(res);
               const data = res.json();
               console.log(data);
               if (data.error == null) {
                   return data.result;
               } else if (data.error != null) {
                  throw data.error;
               }
               throw data.error;
           }
       ).catch(
          (error) => {
             this.router.navigate(['/error',3],{queryParams: {desc:'Server error'}});
             return Observable.throw(error);
          }
       );
    }
    

    希望对你有帮助:)

    【讨论】:

      猜你喜欢
      • 2020-08-24
      • 1970-01-01
      • 1970-01-01
      • 2015-03-15
      • 2011-09-23
      • 1970-01-01
      • 2018-04-15
      • 1970-01-01
      • 2023-03-18
      相关资源
      最近更新 更多