java - 启用从 AngularJS 到 Jersey 的 CORS 发布请求

标签 java angularjs rest jersey cors

我正在尝试将 JSON 文档从 AngularJS 应用程序发布到 Jersey REST 服务。请求失败,通知我:

XMLHttpRequest 无法加载 http://localhost:8080/my.rest.service/api/order/addOrder。请求的资源上不存在“Access-Control-Allow-Origin” header 。因此不允许访问源“http://localhost”。

Jersey REST 后置函数

我已经启用(我认为是)适当的 header :Access-Control-Allow-OriginAccess-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 Controller

我已经声明了应用程序并使用类似 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";
 }]);

我还创建了这个 Controller 来打开模式并处理表单:

    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);

没用,我试过了:

  • 从响应 header 中删除 .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();       
}

这个 Controller 工作正常:

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:

我已经在同一来源的基础上尝试了相同的请求,本质上是与来自 locahost:8080 的 REST 服务一起为 Angular 应用程序提供服务。此配置有效,但需要对我在上面编辑的代码进行轻微更改和一些常规清理。

作为 CORS 请求,Post 仍然失败,因此我仍在寻找此配置中缺失的部分。

更新#2:

我调查了工作请求的 header ,因为它们被传送到浏览器并将它们与非工作请求进行了比较。

工作 get 请求返回以下 header 及其响应: Working GET Request Response

非工作发布请求返回 header 及其响应,但缺少 Access-Control-Allow-Origin header :

Non-working POST Request Response

我相信现在这已经成为一个问题,即在将响应返回给客户端之前将 header 从响应中剥离,这将导致浏览器请求失败。

更新#3:

从 Chrome 的 REST 控制台扩展程序向同一 URL 提交测试 POST 请求会返回适当的响应 header ,如下面的屏幕截图所示。 REST Console Screencap

此时,我无法确定是什么删除了 Jersey 和我的 Angular 客户端之间的 header ,但我相当有信心这就是罪魁祸首。

最佳答案

事实证明,问题是在使用正确的交叉来源 header 的 POST 请求之前,在飞行前发送的 OPTIONS 请求处理不当。

我能够通过下载并实现在此页面找到的 CORS 过滤器来解决问题:http://software.dzhuvinov.com/cors-filter-installation.html .

如果您遇到类似的问题,请按照说明进行测试以查看您的 OPTIONS 请求不再失败,并且紧随其后的是成功的请求。

关于java - 启用从 AngularJS 到 Jersey 的 CORS 发布请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25860490/

相关文章:

java - Thorntail 中 MicroProfile Config 实现的可移植性问题

java - NoSuchSessionException session ID 为空。调用 quit() 后使用 WebDriver?并行运行 java 测试时

java - Android:Java:Proguard:如何:验证我的 jar(不同的 jar 项目)/apk 是否已成功处理? (我正在考虑对其进行逆向工程)

java - 前端或后端的 api 错误消息的国际化?

rest - 用于运行分面搜索的 Alfresco API

javascript - 调试 Angular 的摘要周期 : How to find the cause of an infinite loop?

javascript - 我的 $asyncValidator 不工作 - Angular Javascript

php - JSON 中位置 43 的意外标记

java - Spring boot Rest API嵌套JSON对象为空

c# - REST API token 认证