HerokuのExpress / Node.jsアプリケーションへのCORS RESTリクエストを許可する


97

ChromeのjsコンソールやURLバーなどからのリクエストに対して機能するnode.jsの高速フレームワークでREST APIを作成しました。別のアプリで、別のアプリからのリクエストに対して機能するようにしていますドメイン(CORS)。

javascriptフロントエンドによって自動的に作成された最初のリクエストは/ api / search?uri =に対するものであり、「プリフライト」OPTIONSリクエストで失敗しているようです。

私の高速アプリでは、次のコマンドを使用してCORSヘッダーを追加しています。

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

    // intercept OPTIONS method
    if ('OPTIONS' == req.method) {
      res.send(200);
    }
    else {
      next();
    }
};

そして:

app.configure(function () {
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(allowCrossDomain);
  app.use(express.static(path.join(application_root, "public")));
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

Chromeコンソールから次のヘッダーを取得します。

リクエストURL:http://furious-night-5419.herokuapp.com/api/search?uri = http%3A%2F%2Flocalhost%3A5000%2Fcollections%2F1%2Fdocuments%2F1

リクエスト方法:OPTIONS

ステータスコード:200 OK

リクエストヘッダー

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, x-annotator-auth-token, accept
Access-Control-Request-Method:GET
Connection:keep-alive
Host:furious-night-5419.herokuapp.com
Origin:http://localhost:5000
Referer:http://localhost:5000/collections/1/documents/1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5

クエリ文字列パラメーター

uri:http://localhost:5000/collections/1/documents/1

応答ヘッダー

Allow:GET
Connection:keep-alive
Content-Length:3
Content-Type:text/html; charset=utf-8
X-Powered-By:Express

これは、APIアプリケーションによって送信される適切なヘッダーの欠如のように見えますか?

ありがとう。


記述していないコードでこのエラーが発生しますが、OPTIONSメソッドのハンドラーの必要性がわかりません。誰かがPOSTPOST OPTIONSメソッドの両方を処理するのではなく、メソッドだけを処理しない理由を理解するのを助けてくれませんか?
Ulysses Alves 2016年

リソースを更新するPATCH代わりにそれを使用する場合も含めたい場合がありますPUT
Danny

回答:


65

クリーンなExpressJSアプリでコードをチェックしましたが、問題なく動作します。

app.use(allowCrossDomain)configure関数の先頭に移動してみてください。


8
app.use(app.router);乾杯の前に定義する必要があるためです。
ミハル

私の場合、req.method == 'OPTIONS'のときにres.send(200)を送り返した後、次のPOSTが呼び出されていません。他に何か不足していますか?
アルド

2Aldo:コードが必要です。いくつかのヘッダーを忘れていませんか?サーバーがプリフライトOPTIONSリクエストを正しく処理した後、クライアントがPOSTを送信しない場合は、開発者ツールコンソールを確認してください。WebKitはこの種のエラーをWebインスペクターのコンソールに記録します。
Olegas

1
@ConnorLeechとてもいいです。私は上記のようにallowCrossDomainアプローチを行っていて、そのすべてのヘッダー管理に対処するのにうんざりしていました。また、開発にはCORSのみが必要だったため、何が起こっているのかを把握するために多くのサイクルを費やすことは意味がありませんでした。これを簡単に許可するためのnode.jsサポートがあります。
Steven

1
@ConnorLeech回答としてコメントを追加する必要があると思います...御馳走のように機能し、それは素晴らしくてシンプルです
drmrbrewer '19

4

クレデンシャルでcookieをサポートするには、この行が必要です xhr.withCredentials = true;

mdn docs xhr.withCredentials

OLAP Serverでは、このブロックを他のすべてのブロックの前に追加します。

`app.all('*', function(req, res, next) {
     var origin = req.get('origin'); 
     res.header('Access-Control-Allow-Origin', origin);
     res.header("Access-Control-Allow-Headers", "X-Requested-With");
     res.header('Access-Control-Allow-Headers', 'Content-Type');
     next();
});`

4

元の投稿がコメントとして入力されたため、このページを初めて見たときに本当に見落とされたため、これを回答として追加します。

@ConnorLeechが上記の受け入れられた回答に対する彼のコメントで指摘しているように、当然のことながら、corsと呼ばれる非常に便利なnpmパッケージがあります。使用方法はvar cors = require('cors'); app.use(cors());(これもLeech氏の回答から引用)と同じくらい簡単で、ドキュメントで概説されているように、より厳密で構成可能な方法で適用することもできます。

上記で言及した元のコメントが2014年に行われたことも指摘する価値があるかもしれません。現在は2019年であり、npmパッケージのgithubページを見ると、リポジトリが最近9日前に更新されています。


0

この質問を閲覧するほとんどの人には当てはまりませんが、これとまったく同じ問題があり、解決策はに関連していませんでしたCORS

JSON Web Tokenシークレットstringが環境変数で定義されていないため、トークンに署名できないことがわかりました。これによりPOST、トークンの確認または署名に依存してタイムアウトを取得し、503エラーを返すリクエストが発生し、ブラウザにに問題がCORSあることを通知しましたが、問題はありません。Herokuに環境変数を追加することで問題は解決しました。

これが誰かの役に立つことを願っています。


はい、それが私の問題でした。問題をどのように解決したか、具体的に教えてください。私はまだ開発中で、Express.js w / node corsパッケージで実行しています。
アラン

@alan私はアプリケーションでトークンを検証するためにプロミスを使用していました。JWTシークレットが定義されていない場合、プロミスは解決されません。参照がさらに必要な場合に使用していたコードを次に示します
CatBrownie 2017年

ご返信いただきありがとうございます。コードを調べます。秘密で私はあなたが2番目の秘密鍵について話していると思います。私はoauth2を使用しています。
アラン

失敗した約束があると、この誤解を招くエラーが発生することを付け加えておきます。使用されているノードのバージョンを明示する必要がありました。それ以外の場合、データベースの呼び出し(mongo)が単純にハングし、ブラウザーが503とCors関連の愚かさを教えてくれただけでした。このエラーは、私がapp.use(cors());行っていた最長の時間を本当に混乱させました。
alphanumeric0101
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.