【发布时间】:2014-11-09 17:08:27
【问题描述】:
我正在尝试将 JSON 文档从 AngularJS 应用程序发布到 Jersey REST 服务。请求失败,通知我:
XMLHttpRequest cannot load http://localhost:8080/my.rest.service/api/order/addOrder. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
Jersey REST 发布功能
我已启用(我认为是)相应的标头:Access-Control-Allow-Origin 和 Access-Control-Allow-Methods 在响应中,如下面的方法所示:
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/addOrder")
public Response addOrder(DBObject dbobject) {
DB db = mongo.getDB("staffing");
DBCollection col = db.getCollection("orders");
col.insert(dbobject);
ObjectId id = (ObjectId)dbobject.get("_id");
return Response.ok()
.entity(id)
.header("Access-Control-Allow-Origin","*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.allow("OPTIONS")
.build();
}
Angular JS 控制器
我已经声明了应用程序并使用类似 Stack Overflow 问题中建议的所有设置配置了 $httpProvider:
var staffingApp = angular.module('myApp', ['ngRoute', 'ui.bootstrap']);
myApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
}]);
我还创建了这个控制器来打开一个模式并处理表单:
var modalCtrl = function($scope, $modal, $log, $http, $location) {
$scope.order = {
activityTitle : null,
anticipatedAwardDate : null,
component : null,
activityGroup : null,
activityCategory : null,
activityDescription : null
};
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'addOrder.html',
windowClass: 'modal',
controller: modalInstanceCtrl,
resolve: {
order : function () {
return $scope.order;
}
}
});
modalInstance.result.then(function (oid) {
$log.info("Form Submitted, headed to page...");
$location.path("/orders/" + oid);
}, function() {
$log.info("Form Cancelled")
});
};
};
var modalInstanceCtrl = function ($scope, $modalInstance, $log, $http, order) {
$scope.order = order,
$scope.ok = function () {
$log.log('Submitting user info');
$log.log(order);
$log.log('And now in JSON....');
$log.log(JSON.stringify(order));
$http.post('http://localhost:8080/my.rest.service/api/order/addOrder', JSON.stringify(order)).success(function(data){
$log.log("here's the data:\n");
$log.log(data);
$modalInstance.close(data._id.$oid)
});
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
myApp.controller('modalCtrl', modalCtrl);
没用,我试过了:
- 从响应标头中删除
.allow("OPTIONS")。 - 从应用程序中删除 $httpProvider 配置
- 将 $httpProvider 配置更改为调用 myApp.config(function ($httpProvider) {...}),传递函数本身而不是数组。
获取请求使用相同的配置:
@GET
@Path("/listall/")
@Produces(MediaType.APPLICATION_JSON)
public Response listAll(){
DB db = mongo.getDB("staffing");
DBCollection col = db.getCollection("orders");
List<DBObject> res = col.find().limit(200).toArray();
return Response.ok()
.entity(res.toString())
.header("Access-Control-Allow-Origin","*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.allow("OPTIONS")
.build();
}
这个控制器可以正常工作:
myApp.controller('orderListCtrl', function ($scope, $http){
$http.get('http://localhost:8080/my.rest.service/api/order/listall').success(function(data) {
for (var i = 0; i < data.length; i++) {
if (data[i].description.length > 200) {
data[i].shortDesc = data[i].description.substring(0,196) + "...";
} else {
data[i].shortDesc = data[i].description;
}
};
$scope.orders = data;
});
});
更新 #1:
我已经在同一个来源的基础上尝试了相同的请求,本质上是为 Angular 应用程序提供服务以及来自 locahost:8080 的 REST 服务。此配置有效,但需要在我上面编辑的代码中进行轻微更改和一些常规清理。
作为 CORS 请求,Post 仍然失败,但是我仍在寻找此配置中缺少的部分。
更新 #2:
我调查了工作请求的标头,因为它们被传递到浏览器,并将它们与非工作请求进行了比较。
有效的 get 请求会返回以下标头及其响应:
不工作的 post 请求返回标头及其响应,但缺少 Access-Control-Allow-Origin 标头:
我认为这现在已经成为一个问题,即在将响应返回给客户端之前将标头从响应中剥离,这将导致浏览器无法请求。
更新#3:
从 Chrome 的 REST 控制台扩展向同一 URL 提交测试 POST 请求会返回相应的响应标头,如下面的屏幕截图所示。
此时,我无法确定是什么删除了 Jersey 和我的 Angular 客户端之间的标头,但我相当有信心这是罪魁祸首。
【问题讨论】:
标签: java angularjs rest jersey cors