HTTP 基本認証を使用した GET リクエストがノードでは成功するが、ブラウザーでは失敗するという問題を診断しようとして立ち往生しています。この問題は、CORS の失敗として直接現れます (401 ページに Access-Control-Allow-Origin がありません)。
request.js:119 OPTIONS http://HOST?PARAMS 401 (Unauthorized)
ClientRequest._onFinish @ request.js:119
(anonymous) @ request.js:61
...
17:53:59.170 localhost/:1 Failed to load http://HOST?PARAMS: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9966' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
リクエストは次のようになります。
const request = require("request-promise");
const options = {"url":"http://...?","auth":{"user":"...","pass":"..."},"json":true,"qs":{...},"headers":{},"resolveWithFullResponse":true}
request.get(options).then(...);
このリクエストが Chrome でどのように表示されるか:
ここで私にとって驚くべきこと:
- メソッドは GET ではなく OPTIONS です。(私は明示的に要求しませんでした。)
- 認証資格情報がヘッダーに含まれていません (設定していませんが)
sendImmediately: false
- 「暫定ヘッダーが表示されます」という警告。
私が知りたいこと:
- これは予想される動作ですか?
- そうでない場合、何が問題になっていますか?
- はいの場合、何が問題になっていますか? :)
コマンドラインで同等のリクエストを実行すると、うまくいくようです:
curl -I 'http://MYUSERNAME:MYPASSWORD@SAMEURL?SAME=PARAMETERS' -H 'Origin: http://localhost:4466' -X OPTIONS
HTTP/1.1 200 OK
Date: Wed, 20 Jun 2018 07:29:28 GMT
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: http://localhost:4466
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials
Vary: Origin
X-Frame-Options: SAMEORIGIN
Allow: GET,HEAD,POST,OPTIONS
Content-Length: 0
ただし、URL で提供される資格情報がないと、応答に CORS ヘッダーがないことに気付きました。
HTTP/1.1 401 Unauthorized
Date: Wed, 20 Jun 2018 07:45:26 GMT
Server: Apache/2.4.29 (Unix) OpenSSL/1.0.2l
WWW-Authenticate: Basic realm="Authentication Required"
Content-Length: 381
Content-Type: text/html; charset=iso-8859-1
それは正しい振る舞いですか?
仮説
私は疑う:
- リクエストは「単純なリクエスト」ではないため、ブラウザは OPTIONS 「プリフライト」リクエストを送信する必要があります。(これがリクエストライブラリなのか、ブラウザ自体がこれを行っているのかは完全には明らかではありません)
- 資格情報が提供されていないため、サーバーは 401 を応答していますが、必要な CORS ヘッダーを追加していません。
- CORS ヘッダーがないと、ブラウザは Request ライブラリが結果にアクセスできないようにするため、認証を完了できません。
よくわからないこと:
- サーバーの構成が間違っていませんか?
- リクエストは、OPTIONS プリフライト リクエストで資格情報を渡すことができませんか?