1

バックボーンアプリにクロスドメイン設定を実装しようとしています。

私のサーバー(express.js)はクロスドメインとクレデンシャルを許可しています:

var allowCrossDomain = function(req, res, next) {
  var allowedHost = [
    'http://localhost:3001',
    'http://localhost:7357'
  ];

  if(allowedHost.indexOf(req.headers.origin) !== -1) {
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Origin', req.headers.origin)
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version');
    next();
  } else {
    res.send({auth: false});
  }
}

app.configure(function(){
    ....
    app.use(allowCrossDomain);
    ....
});

私のクライアント(backbone.js)は、クロスドメインも受け入れるように構成されています:

define(["backbone", "jquery", "underscore"], function (BB, $, _) {
  return BB.Model.extend({

    idAttribute: "_id",

    initialize: function () {
      var that = this;

      $.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
        options.crossDomain ={
          crossDomain: true
        };
        options.xhrFields = {
          withCredentials: true
        };
      });
    }
  });
});

コードをテストすると(POSTリクエストを言うと)、非常に特殊な動作をします。

var contacts = new Contacts;
contacts.create({'name': 'my name'});

ブラウザは次のメッセージを返します。

オプション...404(見つかりません)jquery.js:8419

OPTIONShttpメソッドはバックボーンでサポートされていないため、これは完全に混乱しますか?

4

1 に答える 1

7

ほとんどの場合、Expressルートは、GETメソッドPOSTを指定するだけです。例えば、

app.post('/some/api/method', function(req, res) { ... });

これは、POSTsから/ some / api / methodへのルートハンドラーのみを定義したことを意味し、他のメソッド(GETまたはなどOPTIONS)を使用したリクエストは404を返します。

特定の状況(カスタムHTTPヘッダーの送信など)では、 CORSを使用してクロスオリジンURLにXHRリクエストを送信するには、ブラウザが最初にOPTIONSリクエストを発行して、クロスドメインリクエストが許可されているかどうかを確認する必要があります。リクエストが成功した場合( CORSヘッダー付きOPTIONSのHTTP 200 )にのみ、ブラウザは実際のリクエストを行います。

POSTサーバーでルートを定義しただけなので、OPTIONSリクエストは失敗し、ブラウザはリクエストを行いません。OPTIONSリクエストに適切に応答する必要があります。

app.options('/some/api/method', function(req, res) {
    // At this point, the `allowCrossDomain()` middleware will already have
    // taken care of the CORS stuff, so just return OK.
    res.send(200);
});

これで、プリフライトOPTIONSチェックに合格するため、POSTハンドラーへの実際の要求が行われます。


コードに関するボーナスコメント:

  • パフォーマンスの向上:
    • 配列ではなく、オブジェクトを使用して原点を検索および検証します。使用indexOfするには、リクエストごとに配列をゆっくりと反復する必要があります。オブジェクトを使用すると、すばやく検索できます。(JavaScriptオブジェクトは、キーを辞書のようなデータ構造に格納することに注意してください。)
    • allowedHosts 検証関数の外部で定義します。これらは変更されないため、呼び出されるたびに新しいオブジェクトを作成する必要はありませんallowCrossDomain(ガベージコレクションが必要です)。
  • クロスオリジンチェックが失敗した場合は、おそらく失敗したHTTP応答コードを送信する必要があります。

 

var allowedHost = {
  'http://localhost:3001': true,
  'http://localhost:7357': true
};

var allowCrossDomain = function(req, res, next) {
  if(allowedHost[req.headers.origin]) {
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Origin', req.headers.origin)
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version');
    next();
  } else {
    res.send(403, {auth: false});
  }
}
于 2013-01-06T22:47:13.780 に答える