Javascript 从 angularjs 调用 REST 服务时本地主机上的 CORS 问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31612931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CORS issue on localhost while calling REST service from angularjs
提问by Bhramar
I am learning angularJS and trying to implement it in my application.
我正在学习 angularJS 并尝试在我的应用程序中实现它。
I have an RESTful WCF service hosted on localhost IIS. It has a GET method defined to fetch a list of documents : http://localhost:70/DocumentRESTService.svc/GetDocuments/
我在 localhost IIS 上托管了一个 RESTful WCF 服务。它定义了一个 GET 方法来获取文档列表:http://localhost:70/DocumentRESTService.svc/GetDocuments/
Now I am trying to consume this service in my angular app and display the data . Following is the code : HTML :
现在我正在尝试在我的 angular 应用程序中使用此服务并显示数据。以下是代码: HTML :
<html>
<script src="../../dist/js/angular/angular.min.js"></script>
<script src="../../assets/js/one.js"></script>
<body ng-app="myoneapp" ng-controller="oneAppCtrl">
{{"Hello" + "AngularJS"}}
<hr>
<h1> Response from my REST Service </h1>
{{hashValue}}
<hr>
<h1> Response from w3school REST Service </h1>
{{names}}
</body>
</html>
JS:
JS:
angular.module('myoneapp', [])
.controller('oneAppCtrl', function($scope,$http){
$scope.documentValue = {};
$http({method: 'GET',
url: 'http://localhost:70/DocumentRESTService.svc/GetDocuments/',
headers:
{
// 'Access-Control-Allow-Origin': 'http://localhost'
}
})
.success(function(data){ alert('Success!'); $scope.documentValue=data;})
.error(function(data){ alert('Error!'); $scope.documentValue=data; alert('Error!' + $scope.documentValue);})
.catch(function(data){ alert('Catch!'); $scope.documentValue= data;});
$http.get("http://www.w3schools.com/angular/customers.php")
.success(function(response) {$scope.names = response.records;});
});
The strange behavior is this code works perfectly fine in IE11 , whereas it doesn't run in Chrome/Firefox.
奇怪的行为是这段代码在 IE11 中工作得很好,而它不能在 Chrome/Firefox 中运行。
Following is the response in the chrome:(for my REST service) , whereas the REST service from w3schools worked just fine.
以下是 chrome:(for my REST service) 中的响应,而 w3schools 的 REST 服务工作得很好。
{"data":null,"status":0,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"url":"http://localhost:70/DocumentRESTService.svc/GetDocuments/","headers":{"Accept":"application/json, text/plain, /"}},"statusText":""}
{"data":null,"status":0,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"url":" http:/ /localhost:70/DocumentRESTService.svc/GetDocuments/","headers":{"Accept":"application/json, text/plain, /"}},"statusText":""}
Console displayed following error message.
控制台显示以下错误消息。
- [Chrome Console:By opening from filesystem]
- [Chrome 控制台:通过从文件系统打开]
XMLHttpRequest cannot load http://localhost:70/DocumentRESTService.svc/GetDocuments/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'file://' is therefore not allowed access.
XMLHttpRequest 无法加载http://localhost:70/DocumentRESTService.svc/GetDocuments/。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问源 'file://'。
- [Chrome Console:hosted using Brackets]
- [Chrome 控制台:使用括号托管]
XMLHttpRequest cannot load http://localhost:70/DocumentRESTService.svc/GetDocuments/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:55969' is therefore not allowed access.
XMLHttpRequest 无法加载http://localhost:70/DocumentRESTService.svc/GetDocuments/。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问源“ http://127.0.0.1:55969”。
- [Firefox Console:]
- [火狐控制台:]
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:70/DocumentRESTService.svc/GetDocuments/. This can be fixed by moving the resource to the same domain or enabling CORS.
跨域请求被阻止:同源策略不允许读取位于http://localhost:70/DocumentRESTService.svc/GetDocuments/的远程资源。这可以通过将资源移动到同一域或启用 CORS 来解决。
The question here are few:
这里的问题很少:
- Why is localhost or my machineName considered to be a cross-domain request ? I am in the same domain , ain't I ?
- Are there any changes required to do at my service end to enable this behavior? If yes , where in WCF Service ?( based on something i read here)
- an JSONP be useful in this case ? If yes , how would i use it ? would it work with requests that need custom headers ?( NOt really sure what it is , but while resarching found a lot of answers mentioning this. reading links will be helpful. )
- 为什么 localhost 或 my machineName 被认为是跨域请求?我在同一个域中,不是吗?
- 是否需要在我的服务端进行任何更改才能启用此行为?如果是,WCF 服务在哪里?(基于我在此处阅读的内容)
- 在这种情况下,JSONP 有用吗?如果是,我将如何使用它?它可以处理需要自定义标头的请求吗?(不太确定它是什么,但是在重新搜索时发现了很多提到这一点的答案。阅读链接会有所帮助。)
Any help or direction will be helpful.
任何帮助或方向都会有所帮助。
P.S:
PS:
- IDE:Brackets, if that matters .
- AngularJS v1.4.3
- I have referred various stackoverflow questions referring similar problem (CORS) , which involved $resource , $provider , $config , Also some related to deleting some header and adding some value one of the header. I am bit naive to this - any references to this will be helpful.
- IDE:括号,如果这很重要。
- AngularJS v1.4.3
- 我已经提到了各种涉及类似问题 (CORS) 的 stackoverflow 问题,其中涉及 $resource 、 $provider 、 $config ,还有一些与删除某些标头和添加标头中的某个值有关。我对此有点天真 - 对此的任何参考都会有所帮助。
采纳答案by Bhramar
I could resolve this issue. Couple of ways to do so - I am jotting down all that i have tried and their references.
我可以解决这个问题。有几种方法可以做到这一点 - 我正在记下我尝试过的所有内容及其参考资料。
Answer to Ques1.
回答问题1。
'Why is localhost or my machineName considered to be a cross-domain request?'
as @charlietfl mentioned and i Researched here: a different port or subdomain is also consider cross domain by browser.
正如@charlietfl 提到的,我在这里研究过:不同的端口或子域也被浏览器考虑跨域。
Answer to Ques2.
回答问题2。
'Are there any changes required to do at my service end to enable this behavior?'
YES! the change is required on server end itself. The server should respond to the request with
是的!服务器端本身需要更改。服务器应该响应请求
Access-Control-Allow-Origin: *
访问控制允许来源:*
header. Here the * could be replaced with the request header itself or as per your application requirement. Excellent blog hereexplaining the workaround if you're using WCF REST Service. You need to add following line (headers) to each your service method to enable CORS in your service methods.
标题。这里 * 可以替换为请求标头本身或根据您的应用程序要求。如果您使用 WCF REST 服务,这里的优秀博客解释了解决方法。您需要向每个服务方法添加以下行(标题)以在您的服务方法中启用 CORS。
WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Origin", "*"); WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Methods", "POST"); WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Headers", "Content-Type, Accept");
WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Origin", "*"); WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Methods", "POST"); WebOperationContext.Current.OutgoingResponse.Headers.Add(
"Access-Control-Allow-Headers", "Content-Type, Accept");
A specification hereis very helpful for enabling CORS on server / client.
这里的规范对于在服务器/客户端上启用 CORS 非常有帮助。
Answer to Ques3.
回答问题3。
JSONP mostly works for GET requests and aren't most advisable use ,rather enabling CORS is most recommended. (I haven't explored this area much but Wiki& stackoverflow article herewere very descriptive).
JSONP 主要适用于 GET 请求,并不是最可取的用途,而是最推荐启用 CORS。(我没有过多地探索这个领域,但这里的Wiki和 stackoverflow 文章非常具有描述性)。
Apart from that, for testing purpose, a nice chrome extension herecan be helpful. It can be used to assure that the application has CORS issues.
回答by Sendil.J
I struggled for way too long with CORS issues caused by the interaction of an emulated Ionic project (running locally) with some small Node.JS web services (also running locally).
由于模拟的 Ionic 项目(在本地运行)与一些小型 Node.JS Web 服务(也在本地运行)的交互引起的 CORS 问题,我挣扎了太久。
Behold the short easy workaround : Chrome's plugin AllowControlAllowOrigin.
看看简短的简单解决方法:Chrome 的插件 AllowControlAllowOrigin。
Just switch the radio button from red to green, and no more blocked request, error or warning ! Of course it's a temporary solution and you may have to put your hands in your request headers when the time to stop the local tests will come. In the meantime, that's a great way to avoid loosing time on those anoying recurrent issues.
只需将单选按钮从红色切换到绿色,不再有阻塞的请求、错误或警告!当然,这是一个临时解决方案,当停止本地测试的时间到来时,您可能不得不将手放在请求标头中。与此同时,这是避免在那些烦人的反复问题上浪费时间的好方法。
回答by Suresh Selvaraj
If you are facing CORS issue in AngularJS applications while accessing REST API running in localhost machine check the following: Add the CORS Filter in your server application. In my case, I have added the below code in Spring application
如果您在访问 localhost 机器中运行的 REST API 时遇到 AngularJS 应用程序中的 CORS 问题,请检查以下内容:在您的服务器应用程序中添加 CORS 过滤器。就我而言,我在 Spring 应用程序中添加了以下代码
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class SimpleCORSFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);
public SimpleCORSFilter() {
log.info("SimpleCORSFilter init");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
In angularjs code, don't give URL like http://localhost:8080/../. Instead of localhost give your host IP number.
在 angularjs 代码中,不要提供像 http:// localhost:8080/../这样的 URL 。而不是 localhost 提供您的主机 IP 号。
It will work properly
它会正常工作