Я пытаюсь опубликовать документ JSON из приложения AngularJS в службу 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.
Функция отправки 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-контроллер
Я объявил приложение и настроил $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";
}]);
Я также создал этот контроллер, чтобы открыть modal и обработать форму:
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 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 рядом с службой REST от locahost: 8080. Эта конфигурация работала, но требовала небольшого изменения и некоторой общей очистки в моем коде, которую я редактировал выше.
Сообщение по-прежнему не работает как запрос CORS, однако я все еще ищу недостающую часть в этой конфигурации.
Обновление # 2:
Я исследовал заголовки рабочего запроса по мере их доставки в браузер и сравнил их с нерабочим запросом.
Рабочий запрос получения возвращает следующие заголовки с его ответом:
Нерабочий почтовый запрос возвращает заголовки с ответом, но отсутствует заголовок Access-Control-Allow-Origin:
Я считаю, что теперь это стало проблемой, когда заголовки были отстранены от ответа до того, как они вернули его клиенту, что приведет к сбою запроса браузера.
Обновление № 3:
Отправка тестового запроса POST на тот же URL-адрес из консоли Chrome REST Console возвращает соответствующие заголовки ответов, как показано в скринкапе ниже.
На данный момент я не могу определить, как удалить заголовки между Джерси и моим клиентом Angular, но я уверен, что виновник.