Grunt连接任务和中间件Access-Control-Allow-Origin

11

我希望允许跨域调用,这样我就可以执行对服务器的rest API调用。

我的connect grunt任务配置如下:

    connect: {
  options: {
    port: 9000,
    // Change this to '0.0.0.0' to access the server from outside.
    hostname: 'localhost',
    livereload: 35729,
    middleware: function(connect, options, next) {
      return [
        function(req, res, next) {
          res.setHeader('Access-Control-Allow-Origin', '*');
          res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
          res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
          next();
        }
      ];
    }
  },
},
当我运行grunt服务器时,会显示“Cannot GET /”错误。 没有中间件配置时,应用程序可以正常工作并正确加载索引文件。 请指导我哪里做错或遗漏了什么? 我的gruntfile的一些更多细节是,我正在使用yeoman angular种子应用作为我的应用基础。

2
我认为中间件函数不需要传递“next”参数。 - bpaul
是的,上面那一行应该是:middleware: function(connect, options, middlewares)。请参考 https://github.com/gruntjs/grunt-contrib-connect#middleware,在middlewares下的第二个例子。 - ansorensen
4个回答

6

尝试类似以下这样的代码:

connect: {
  options: {
    port: 9000,
    // Change this to '0.0.0.0' to access the server from outside.
    hostname: 'localhost',
    livereload: 35729,

    // remove next from params
    middleware: function(connect, options) {
      return [
        function(req, res, next) {
          res.setHeader('Access-Control-Allow-Origin', '*');
          res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
          res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

          // don't just call next() return it
          return next();
        },

        // add other middlewares here 
        connect.static(require('path').resolve('.'))

      ];
    }
    },
    },

我刚刚尝试了您的更改,但仍然无法使应用程序正常工作。关于我的gruntfile的一些更多细节是,我正在使用yeoman angular seed应用程序作为我的应用程序基础。 - Maria Stellini
1
如果您正在使用Yeoman,您应该将以下内容添加到中间件中:connect.static(require('path').resolve(yeomanConfig.app)); - bpaul
这仍然在firebug中给我“跨域请求被阻止”。除了上面的设置,还需要做什么才能使CORS工作? - Adrian Rosca

2
致敬bpaul,他引导我找到了正确的答案。在类似问题的回复格式将适用于此处。
将“next”替换为“middlewares”,并将您的匿名函数推入中间件数组中,然后返回它即可。
middleware: function(connect, options, middlewares) {

    middlewares.unshift(function(req, res, next) {
        res.setHeader('Access-Control-Allow-Credentials', true);
        res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
        next();
    });

    return middlewares;
}

是的,我更喜欢这种中间件的实现方式。谢谢。 - bpaul

0

Grunt connect带有多个中间件,存储为数组中的函数。当您通过返回一个数组来设置中间件时,您将覆盖负责提供页面的现有中间件。

根据ansorensen在文档中的评论https://github.com/gruntjs/grunt-contrib-connect#middleware,相关部分如下。

options: {
    middleware: function(connect, options, middlewares) {
      // inject a custom middleware into the array of default middlewares
      middlewares.unshift(function(req, res, next) {
        if (req.url !== '/hello/world') return next();

        res.end('Hello, world from port #' + options.port + '!');
      });

      return middlewares;
    },
},

数组中较早的中间件比后面的中间件先生效。

所以你想要的是

connect: {
    options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729,

        // remove next from params
        middleware: function(connect, options, middlewares) {
            middlewares.unshift(function(req, res, next) {
                res.setHeader('Access-Control-Allow-Origin', '*');
                res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
                res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

                return next();
            });

            return middlewares;
        }
    },
},

0
connect: {
  options: {
    port: 9000,
    // Change this to '0.0.0.0' to access the server from outside.
    hostname: 'localhost',
    livereload: 35729,
    middleware: function(connect, options, next) {
      return [
        function(req, res, next) {
         res.header('Access-Control-Allow-Credentials', true);
         res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
         res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
         next();
      }];
     }
   };

这将帮助您获得get调用Access-Control-Allow-Credentials的访问权限


尝试了更改,但仍然没有运气..不知道我做错了什么。 - Maria Stellini
以上代码会抛出错误,因为res对象没有header方法。你需要使用res.setHeader方法。 - ansorensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接