今天一位同事问了我一个有趣的问题:
我相信你在本地使用 IONIC SERVE 时可能遇到过这个错误。
XMLHttpRequest 无法加载 http://something.mybluemix.net/rest/audit/list。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许访问源“http://localhost:8100”。
本质上,我是通过工厂的 $http.get() 方法调用 URL。 Ionic 似乎有多种调用 REST 服务的方法(1.$http 或 2.ngResource)。
所以我的问题是,您是否有解决此问题的方法或从 Ionic 内部处理/调用 REST 服务的首选方式?任何示例代码将不胜感激。
这是一个很好的问题,因为有多种方法可以处理这个问题。在我们开始之前,让我们回顾一下。这个错误是什么,为什么我们会得到它?浏览器有一个安全模型,可以防止从一个域到另一个域的 Ajax 请求。这就是导致创建 JSON/P 的原因,它本质上是调用远程服务的一种变通方法。
使用 Cordova 时,您不必担心。但是当使用 Ionic Serve 并在浏览器中运行应用程序时,您必须想办法解决它。尽管使用 JSON/P 很简单,但我倾向于尝试避免将代码添加到我的 Cordova/Ionic 应用程序中,这些代码只是为了使其在桌面浏览器上运行。需要明确的是,我有时会这样做,但我尽量避免这样做。 (事实上,下面的答案之一将涉及这样的修改。)那么鉴于此,有哪些选择?
1)启用CORS
现代浏览器支持 CORS,这是远程 API 表示您的代码可以从另一个域调用它的一种方式。如果您有权访问 API(因此您正在构建移动端和服务器端),那么为您的 API 启用 CORS 是微不足道的。你如何做到这一点当然取决于语言。我描述了如何在
ColdFusion
中执行此操作,您可以使用
Node.js/Express
快速启用它。
2)用扩展破解
您可以找到一个 Chrome 扩展程序(
此处为它的超长 URL
),它将在您的应用程序中动态修改 CORS 标头。显然这只是 Chrome,但我喜欢它在任何地方都可以零更改工作。
3) 离子服务代理
你知道 Ionic Serve 本身有代理功能吗?在他们的
Testing in a Browser
文档页面中,他们讨论了如何修改 ionic.project 文件中的设置以添加代理。这是一个例子。
{
"name": "appname",
"email": "",
"app_id": "",
"proxies": [
{
"path": "/v1",
"proxyUrl": "https://api.instagram.com/v1"
}
]
}
完成后,对 /v1 的请求将通过代理在本地重定向到 api.instagram.com/v1。这是一个很酷的功能,但它确实意味着您的代码必须更改。请注意,您可以通过检查浏览器平台(如此处所述 - 平台类 )或使用 ionic.Platform 来稍微简化这一过程。 哎呀,刮那个! 我很自然地假设如果添加 CSS 元素来标记浏览器平台,那么 ionic.Platform 也会支持它,但据我所知它不支持。我为此提交了 问题 4306 。
注意——我对此做了一些快速测试,基本上是 console.logging:
{
"name": "appname",
"email": "",
"app_id": "",
"proxies": [
{
"path": "/v1",
"proxyUrl": "https://api.instagram.com/v1"
}
]
}
奇怪的是,在 Ionic 的运行块中,甚至在 $ionicPlatform.ready 中,该类也不存在。它只存在于我的第一个控制器中。这似乎……对我来说是错误的。
好的,所以更多的测试。在
ionic.Platform
的文档中,他们提到了一个平台数组。你可以这样做:
ionic.Platform.platforms.contains("browser")
看看你是否在浏览器上。所以我的issue 4306有点不对。您可以检查 - 但似乎 isBrowser 辅助实用程序应该可用。
所以——总结一下——你有多种不同的处理方式——有些需要对代码进行一些更改,有些则不需要。找到最适合您的那一款,然后顺其自然。