为啥我的 Meteor API 中仍然出现“Access-Control-Allow-Origin”?

Posted

技术标签:

【中文标题】为啥我的 Meteor API 中仍然出现“Access-Control-Allow-Origin”?【英文标题】:Why am I still getting 'Access-Control-Allow-Origin' in my Meteor API?为什么我的 Meteor API 中仍然出现“Access-Control-Allow-Origin”? 【发布时间】:2015-02-03 08:10:33 【问题描述】:

我收到此错误:

XMLHttpRequest cannot load http://xyz.meteor.com/api/posts/b7shrmshYZ85wsFLZ. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.jquery.com' is therefore not allowed access. 

即使我已经在我的代码中编写了这个错误,我仍然会收到此错误。

this.response.setHeader("Access-Control-Allow-Origin", "*");
this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

这里有什么我遗漏的吗?我从以下位置获取代码:

https://github.com/awatson1978/rest-api

但是我已经大量修改了路径以更加 RESTful。

//==============================================================================
// the following is a REST API that only uses the POST portion of the HTTP protocol
// and is suitable for automated browser testing

// be aware that POSTS refers to the HTTP protocol
// while 'posts' and 'Posts' refers to the weblog example used in the Meteor Cookbook
// this particular example has a slight bit of name-collision occurring


// api:      http://localhost:3000/api/posts
// example:  http://localhost:3000/api/posts
Router.route('/api/posts', function()
  if (this.request.method == 'GET') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.find().fetch()
    ));
   else if (this.request.method == 'POST') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.insert(this.request.body)
    ));
   else 
    this.response.statusCode = 405;
    this.response.end("Invalid Request Type");
  ;
, where: 'server');

// api:      http://localhost:3000/api/posts/:postId
// example:  http://localhost:3000/api/posts/314159
Router.route('/api/posts/:postId', function()
  if (!Posts.findOne(_id: this.params.postId)) 
    this.response.statusCode = 404;
    this.response.end("Invalid Request Type");
   else if (this.request.method == 'GET') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.findOne(_id: this.params.postId )
    ));
   else if (this.request.method == 'PUT') 
    Posts.update(_id: this.params.postId ,$set: this.request.body);
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.findOne(_id: this.params.postId )
    ));
   else if (this.request.method == 'DELETE') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.remove(_id: this.params.postId )
    ));
   else 
    this.response.statusCode = 405;
    this.response.end("Invalid Request Type");
  ;
, where: 'server');

Router.route('/api/posts/search/:user', function()
  if (this.request.method == 'GET') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.find(  user: this.params.user  ).fetch()
    ));
   else 
    this.response.statusCode = 405;
  ;
, where: 'server');

编辑:

没关系,想通了。我失踪了,需要大量重构:

this.request.method == 'OPTIONS'

//==============================================================================
// the following is a vanilla REST API that uses the entire HTTP protocol

// api:      http://localhost:3000/api/posts
// example:  http://localhost:3000/api/posts

// api:      http://localhost:3000/api/posts/:postId
// example:  http://localhost:3000/api/posts/12345

// api:      http://localhost:3000/api/posts/search/:username
// example:  http://localhost:3000/api/posts/search/bill

Router.route('/api/posts', function()
  // console.log('################################################');
  // console.log(this.request.method);
  // console.log(this.request.headers);
  // console.log('this.params.postId: ' + this.params.postId);
  //
  // console.log('------------------------------');
  // console.log(this.request.body);
  // console.log('------------------------------');

  this.response.statusCode = 200;
  this.response.setHeader("Content-Type", "application/json");
  this.response.setHeader("Access-Control-Allow-Origin", "*");
  this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

  if (this.request.method == 'GET') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      list_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.find().fetch()
    ));
   else if (this.request.method == 'POST') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      insert_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.insert(this.request.body)
    ));
   else if (this.request.method == 'OPTIONS') 
    this.response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, OPTIONS");
    this.response.end("OPTIONS Response");
  
, where: 'server');


Router.route('/api/posts/:postId', function()
  // console.log('################################################');
  // console.log(this.request.method);
  // console.log(this.request.headers);
  // console.log('this.params.postId: ' + this.params.postId);
  //
  // console.log('------------------------------');
  // console.log(this.request.body);
  // console.log('------------------------------');

  this.response.statusCode = 200;
  this.response.setHeader("Content-Type", "application/json");
  this.response.setHeader("Access-Control-Allow-Origin", "*");
  this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

  //Access-Control-Allow-Origin: http://foo.example
  //Access-Control-Allow-Methods: POST, GET, OPTIONS
  //Access-Control-Allow-Headers: X-PINGOTHER

  if (this.request.method == 'GET') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      get_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.findOne(_id: this.params.postId )
    ));
   else if (this.request.method == 'PUT') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      update_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.update(_id: this.params.postId,$set: this.request.body)
    ));
   else if (this.request.method == 'DELETE') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      delete_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.remove(_id: this.params.postId )
    ));
   else if (this.request.method == 'OPTIONS') 
    this.response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, OPTIONS");
    this.response.end("OPTIONS Response With Parameter");
  
, where: 'server');

Router.route('/api/posts/search/:user', function()
  // console.log('################################################');
  // console.log(this.request.method);
  // console.log(this.request.headers);
  // console.log('this.params.postId: ' + this.params.postId);
  //
  // console.log('------------------------------');
  // console.log(this.request.body);
  // console.log('------------------------------');

  this.response.statusCode = 200;
  this.response.setHeader("Content-Type", "application/json");
  this.response.setHeader("Access-Control-Allow-Origin", "*");
  this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

  //Access-Control-Allow-Origin: http://foo.example
  //Access-Control-Allow-Methods: POST, GET, OPTIONS
  //Access-Control-Allow-Headers: X-PINGOTHER

  if (this.request.method == 'GET') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      get_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.find(  user: this.params.user  ).fetch()
    ));
  ;
, where: 'server');

【问题讨论】:

那你能把你的问题的答案贴出来并接受吗?为后人所知。 【参考方案1】:

没关系,想通了。我错过了这个:

this.request.method == 'OPTIONS'

我的代码还需要大量重构。

//==============================================================================
// the following is a REST API that only uses the POST portion of the HTTP protocol
// and is suitable for automated browser testing

// be aware that POSTS refers to the HTTP protocol
// while 'posts' and 'Posts' refers to the weblog example used in the Meteor Cookbook
// this particular example has a slight bit of name-collision occurring


// api:      http://localhost:3000/api/posts
// example:  http://localhost:3000/api/posts
Router.route('/api/posts', function()
  if (this.request.method == 'GET') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.find().fetch()
    ));
   else if (this.request.method == 'POST') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.insert(this.request.body)
    ));
   else 
    this.response.statusCode = 405;
    this.response.end("Invalid Request Type");
  ;
, where: 'server');

// api:      http://localhost:3000/api/posts/:postId
// example:  http://localhost:3000/api/posts/314159
Router.route('/api/posts/:postId', function()
  if (!Posts.findOne(_id: this.params.postId)) 
    this.response.statusCode = 404;
    this.response.end("Invalid Request Type");
   else if (this.request.method == 'GET') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.findOne(_id: this.params.postId )
    ));
   else if (this.request.method == 'PUT') 
    Posts.update(_id: this.params.postId ,$set: this.request.body);
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.findOne(_id: this.params.postId )
    ));
   else if (this.request.method == 'DELETE') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.remove(_id: this.params.postId )
    ));
   else 
    this.response.statusCode = 405;
    this.response.end("Invalid Request Type");
  ;
, where: 'server');

Router.route('/api/posts/search/:user', function()
  if (this.request.method == 'GET') 
    this.response.statusCode = 200;
    this.response.setHeader("Content-Type", "application/json");
    this.response.setHeader("Access-Control-Allow-Origin", "*");
    this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    this.response.end(JSON.stringify(
      Posts.find(  user: this.params.user  ).fetch()
    ));
   else 
    this.response.statusCode = 405;
  ;
, where: 'server');
EDIT:

Nevermind, figured it out. I was missing and needed a LOT of refactoring:

this.request.method == 'OPTIONS'

//==============================================================================
// the following is a vanilla REST API that uses the entire HTTP protocol

// api:      http://localhost:3000/api/posts
// example:  http://localhost:3000/api/posts

// api:      http://localhost:3000/api/posts/:postId
// example:  http://localhost:3000/api/posts/12345

// api:      http://localhost:3000/api/posts/search/:username
// example:  http://localhost:3000/api/posts/search/bill

Router.route('/api/posts', function()
  // console.log('################################################');
  // console.log(this.request.method);
  // console.log(this.request.headers);
  // console.log('this.params.postId: ' + this.params.postId);
  //
  // console.log('------------------------------');
  // console.log(this.request.body);
  // console.log('------------------------------');

  this.response.statusCode = 200;
  this.response.setHeader("Content-Type", "application/json");
  this.response.setHeader("Access-Control-Allow-Origin", "*");
  this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

  if (this.request.method == 'GET') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      list_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.find().fetch()
    ));
   else if (this.request.method == 'POST') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      insert_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.insert(this.request.body)
    ));
   else if (this.request.method == 'OPTIONS') 
    this.response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, OPTIONS");
    this.response.end("OPTIONS Response");
  
, where: 'server');


Router.route('/api/posts/:postId', function()
  // console.log('################################################');
  // console.log(this.request.method);
  // console.log(this.request.headers);
  // console.log('this.params.postId: ' + this.params.postId);
  //
  // console.log('------------------------------');
  // console.log(this.request.body);
  // console.log('------------------------------');

  this.response.statusCode = 200;
  this.response.setHeader("Content-Type", "application/json");
  this.response.setHeader("Access-Control-Allow-Origin", "*");
  this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

  //Access-Control-Allow-Origin: http://foo.example
  //Access-Control-Allow-Methods: POST, GET, OPTIONS
  //Access-Control-Allow-Headers: X-PINGOTHER

  if (this.request.method == 'GET') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      get_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.findOne(_id: this.params.postId )
    ));
   else if (this.request.method == 'PUT') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      update_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.update(_id: this.params.postId,$set: this.request.body)
    ));
   else if (this.request.method == 'DELETE') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      delete_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.remove(_id: this.params.postId )
    ));
   else if (this.request.method == 'OPTIONS') 
    this.response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, OPTIONS");
    this.response.end("OPTIONS Response With Parameter");
  
, where: 'server');

Router.route('/api/posts/search/:user', function()
  // console.log('################################################');
  // console.log(this.request.method);
  // console.log(this.request.headers);
  // console.log('this.params.postId: ' + this.params.postId);
  //
  // console.log('------------------------------');
  // console.log(this.request.body);
  // console.log('------------------------------');

  this.response.statusCode = 200;
  this.response.setHeader("Content-Type", "application/json");
  this.response.setHeader("Access-Control-Allow-Origin", "*");
  this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

  //Access-Control-Allow-Origin: http://foo.example
  //Access-Control-Allow-Methods: POST, GET, OPTIONS
  //Access-Control-Allow-Headers: X-PINGOTHER

  if (this.request.method == 'GET') 
    Statistics.update(_id: "configuration",$inc:
      total_count: 1,
      get_count: 1
    );
    this.response.end(JSON.stringify(
      Posts.find(  user: this.params.user  ).fetch()
    ));
  ;
, where: 'server');

【讨论】:

以上是关于为啥我的 Meteor API 中仍然出现“Access-Control-Allow-Origin”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 acc 总是更高但我的 val_acc 很小?

Meteor 版本求解器:为啥“流星更新”会降级软件包?

为啥 Meteor 模板助手不在上下文中返回变量?

为啥当我将 Meteor 应用程序转换为使用 Docker 时,我的 MongoDB 数据会消失?

为啥我的带有帐户包的 Meteor 应用程序没有发送验证电子邮件?

Meteor 应用突然不再在 iOS 上运行