如何从 javascript 调用 IBM Watson 服务

Posted

技术标签:

【中文标题】如何从 javascript 调用 IBM Watson 服务【英文标题】:how to call IBM Watson services from javascript 【发布时间】:2017-08-23 15:04:12 【问题描述】:

我正在使用 IBM Watson 服务实现一个虚拟代理。我的应用程序是使用 Jquery、Angular JS 和 Java 开发的。目前我正在从 java 的中间层调用 watson 服务。但我想避免这种情况并直接从 javascript 调用。当我使用 XML Http 请求从 javascript 调用时,我收到 CORS 错误。如何解决这个问题?

下面是我的代码:

var username = "uid";
var password = "pwd";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'url');
//xhr.withCredentials = true;
xhr.setRequestHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Origin,Content-Type, application/json, Authorization");
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.setRequestHeader('Access-Control-Allow-Credentials', '*');
xhr.setRequestHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
xhr.setRequestHeader('Content-Type', undefined);
xhr.setRequestHeader('Authorization', 'Basic ' + btoa(username + " " + password));
xhr.send('"query":"hi"');

【问题讨论】:

【参考方案1】:

查看 IBM developerWorks 上关于使用 Watson 问答服务的教程 - http://www.ibm.com/developerworks/cloud/library/cl-watson-qaapi-app/index.html#N10229

【讨论】:

这是在节点 js 中。我想要 jquery 或 angular js【参考方案2】:

IBM Watson 服务尚不支持从基于浏览器的应用获取跨域请求。

在Can't access IBM Watson API locally due to CORS on a Rails/AJAX App查看答案:

我们不支持 CORS,我们正在努力,但在您的情况下,尚不支持 Visual Recognition。

这意味着某些服务支持 CORS,但我猜您尝试过的服务不是其中之一。

因此,除了您说您现在正在做的事情(改为从服务器端 Java 层访问服务)之外,您从 Web 应用程序中运行的 JavaScript 代码获取服务的唯一选择是,设置您的拥有https://github.com/Rob--W/cors-anywhere 或类似的服务器端代理,或通过像https://cors-anywhere.herokuapp.com/ 这样的开放CORS 代理发送您的请求(尽管在您的请求包含您的任何类型的身份验证令牌的情况下,您不太可能希望这样做)不想暴露给第三方代理服务的运营商)。

此类代理的工作方式是,您无需使用 https://gateway.watsonplatform.net/some/api 作为在客户端 JavaScript 代码中指定的请求 URL,而是指定代理 URL,例如 https://cors-anywhere.herokuapp.com/https://gateway.watsonplatform.net/some/api,然后代理将实际请求发送到服务,取回响应,并将所需的Access-Control-Allow-Origin响应头和其他头添加到它并传递给它。

因此,包含 CORS 标头的响应就是浏览器所看到的。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 有更多关于 CORS 工作原理的详细信息,但要知道的主要是浏览器是 CORS 的执行点。因此,在使用 Watson 服务的情况下,浏览器实际上会从 Watson API 获得响应——您将能够在浏览器中使用 devtools 来查看响应——但是浏览器会将响应公开给您的客户端 JavaScript 代码仅当响应包含 Access-Control-Allow-Origin 响应标头以指示发送响应的服务器已选择接收来自 Web 应用程序中运行的客户端 JavaScript 的跨域请求时。

这就是为什么,无论如何,上面的 XHR 代码 sn-p 中的所有 xhr.setRequestHeader("Access-Control-Allow- 行都需要删除——因为 Access-Control-Allow-* 标头是 响应 标头,而不是请求标头;在请求中将它们发送到服务器对 CORS 没有影响,因为如上所述,浏览器是 CORS 执行点,而不是服务器。

所以服务器不会收到来自浏览器的请求并说,好的,我看到这个请求有正确的标头,所以我会允许它。相反,服务器允许来自浏览器的所有请求,就像它允许来自非浏览器工具(如 Java 代码或 curl 或 Postman 或其他任何东西)的所有请求(当然,只要它们经过身份验证)并发送响应。

不同之处在于,当非基于浏览器的应用收到响应时,如果它缺少 Access-Control-Allow-Origin 标头,它不会拒绝让您访问响应。但是如果缺少响应,浏览器会拒绝让您的客户端 JavaScript Web 应用代码访问响应。

【讨论】:

【参考方案3】:

您可能还想查看 GitHub 上的一些 Watson SDK's。

【讨论】:

【参考方案4】:

有些 Watson 服务支持 CORS,有些不支持。但是,通过 CORS 访问时,您必须使用 Auth Token 而不是用户名/密码组合*。

这是支持 CORS 的服务的部分列表:https://github.com/watson-developer-cloud/node-sdk/tree/master/examples/webpack#important-notes

以下是几个使用 Node.js SDK 的示例:

Webpack:https://github.com/watson-developer-cloud/node-sdk/tree/master/examples/webpack 浏览:https://github.com/watson-developer-cloud/node-sdk/tree/master/examples/browserify

还有大量使用 Speech JavaScript SDK 的示例:

https://watson-speech.mybluemix.net/

* 有一些服务使用 API 密钥而不是用户名/密码组合。在这种情况下,如果服务支持 CORS,您可以直接从客户端代码中使用 API 密钥。

【讨论】:

以上是关于如何从 javascript 调用 IBM Watson 服务的主要内容,如果未能解决你的问题,请参考以下文章

如何通过使用 JavaScript 的 HTTP 请求从 IBM Cloud 获取 JSON 格式的数据?

IBM Worklight - 无法从客户端应用程序调用适配器过程

如何从.net核心调用ibm watson api

从 javascript 适配器调用 java 代码

如何从 IBM Cloud 函数中获取远程 IP

IBM Watson Assistant:如何通过对话进行 API 调用