[解決済み] REST APIからデータを取得しようとしたときに、要求されたリソースに'Access-Control-Allow-Origin'ヘッダーが存在しない。
質問
HP AlmのREST APIからデータを取り出そうとしています。それは小さなcurlスクリプトでかなりうまく動作します - 私は私のデータを取得します。
今、JavaScript、フェッチとES6(多かれ少なかれ)でそれを行うことは、より大きな問題であるように思えます。私はこのエラーメッセージを得続ける。
Fetch APIはロードできません。プリフライトリクエストへの応答が アクセスコントロールチェックを通過します。Access-Control-Allow-Origin」ヘッダーがありません。 要求されたリソースに存在します。オリジン ' http://127.0.0.1:3000 は ので、アクセスが許可されません。レスポンスにはHTTPステータスコード501が含まれています。 不透明なレスポンスが必要な場合は、リクエストのモードを no-cors' は、CORS を無効にしてリソースを取得します。
これは、私が自分のローカルホスト内からそのデータを取得しようとしているためであり、解決策はCORSを使用することであるべきだと理解しています。今私は実際にそれをしたと思ったが、どういうわけかそれは私がヘッダーに書いたものを無視するか、問題は他の何かであるか?
つまり、実装に問題があるのでしょうか?私のやり方が悪いのでしょうか?残念ながらサーバーのログを確認することができません。本当にちょっと困っています。
function performSignIn() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
headers.append('GET', 'POST', 'OPTIONS');
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
fetch(sign_in, {
//mode: 'no-cors',
credentials: 'include',
method: 'POST',
headers: headers
})
.then(response => response.json())
.then(json => console.log(json))
.catch(error => console.log('Authorization failed : ' + error.message));
}
私はChromeを使用しています。また、そのChrome CORS Pluginを使用してみましたが、別のエラーメッセージが表示されます。
レスポンスに含まれる 'Access-Control-Allow-Origin' ヘッダーの値は、以下のとおりです。 リクエストの認証モードが「*」の場合、ワイルドカード「*」であってはなりません。 'include'です。オリジン ' http://127.0.0.1:3000 は許可されません。 にアクセスできるようになります。によって開始されるリクエストの認証情報モード。 XMLHttpRequest は withCredentials 属性によって制御される。
解決方法は?
この回答は多くの分野をカバーしているので、3つのパートに分かれています。
- CORS プロキシを利用して "Access-Control-Allow-Originヘッダがない" 問題点
- CORSプリフライトを回避する方法
- 修正方法 "Access-Control-Allow-Originヘッダーは、ワイルドカードであってはならない" 問題点
CORS プロキシを使用した場合の回避方法 "Access-Control-Allow-Originヘッダがない" 問題点
フロントエンドのコードがリクエストを送るサーバーをコントロールできず、そのサーバーからのレスポンスに問題がある場合、単に必要な
Access-Control-Allow-Origin
ヘッダがある場合でも、CORS プロキシを経由してリクエストを行うことで、動作させることができます。
のコードで簡単に独自のプロキシを実行することができます。
https://github.com/Rob--W/cors-anywhere/
.
また、自作のプロキシをHerokuにデプロイするのも、5つのコマンドで2~3分程度で簡単にできます。
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
これらのコマンドを実行した後、あなた自身のCORS Anywhereサーバーが、例えば、次の場所で動作していることになります。
https://cryptic-headland-94862.herokuapp.com/
.
ここで、リクエストURLの前に、プロキシ用のURLを付けます。
https://cryptic-headland-94862.herokuapp.com/https://example.com
プロキシURLをプレフィックスとして追加することで、リクエストがプロキシを経由して行われるようになります。
-
リクエストの転送先
https://example.com
. -
からの応答を受信する。
https://example.com
. -
を追加します。
Access-Control-Allow-Origin
ヘッダをレスポンスに追加します。 - ヘッダーを追加したレスポンスを、リクエストしているフロントエンドのコードに戻します。
ブラウザは、フロントエンドのコードがそのレスポンスにアクセスすることを許可します。なぜなら、そのレスポンスは
Access-Control-Allow-Origin
レスポンスヘッダはブラウザが見るものです。
これは、ブラウザがCORSプリフライトを行うトリガーとなるようなリクエストであっても機能します。
OPTIONS
リクエストの場合、プロキシは
Access-Control-Allow-Headers
と
Access-Control-Allow-Methods
ヘッダはプリフライトを成功させるために必要なものです。
CORSプリフライトを回避する方法
質問のコードは、CORSプリフライトをトリガーします。
Authorization
ヘッダを生成します。
https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
それを抜きにしても
Content-Type: application/json
ヘッダもプリフライトのトリガーとなります。
プリフライト」の意味:ブラウザが
POST
を送信します。
OPTIONS
リクエストをサーバーに送信し、サーバーがクロスオリジンの
POST
を持つ
Authorization
と
Content-Type: application/json
ヘッダを作成します。
小さなcurlスクリプトでかなりうまくいきます - 私のデータを取得します。
で適切にテストするために
curl
を使用するには、プリフライトをエミュレートする必要があります。
OPTIONS
ブラウザが送信します。
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
...と共に
https://the.sign_in.url
を、実際の
sign_in
のURLです。
ブラウザが必要とする応答は、その
OPTIONS
リクエストには、次のようなヘッダが必要です。
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
もし
OPTIONS
レスポンスにこれらのヘッダが含まれていない場合、ブラウザはそこで停止し、決して
POST
リクエストに対応します。また、レスポンスの HTTP ステータスコードは 2xx である必要があり、通常は 200 か 204 です。それ以外のステータスコードであれば、ブラウザはそこで停止します。
問題のサーバーは
OPTIONS
リクエストのステータスコードは 501 で、これは明らかに
OPTIONS
リクエストに対応します。他のサーバーはこの場合、通常、405 "Method not allowed" というステータスコードで応答します。
そのため、決して
POST
に応答した場合、フロントエンドのJavaScriptコードからそのサーバーに直接リクエストすることができます。
OPTIONS
リクエストに 405 や 501、あるいは 200 や 204 以外の応答があった場合、あるいは必要な応答ヘッダがない場合は、そのような応答があります。
質問のケースでプリフライトを発動させない方法は、次のようになります。
-
もしサーバーが
Authorization
リクエストヘッダの本文に埋め込まれた認証データに依存しています。POST
リクエスト、またはクエリパラメータとして -
を必要としない場合、サーバは
POST
ボディにContent-Type: application/json
というメディアタイプを受け入れましたが、代わりにPOST
のボディをapplication/x-www-form-urlencoded
という名前のパラメータを持つjson
(またはその他)のJSONデータです。
修正方法 "Access-Control-Allow-Originヘッダーは、ワイルドカードであってはならない" 問題点
<サブ 別のエラーメッセージが表示されるのですが。
<サブ レスポンスに含まれる 'Access-Control-Allow-Origin' ヘッダーの値 <サブ は、リクエストの認証モードが <サブ 'include'を使用します。オリジン '
http://127.0.0.1:3000
は許可されません。 <サブ にアクセスできるようになります。によって開始されるリクエストのクレデンシャルモードは XMLHttpRequest は withCredentials 属性によって制御される。
認証情報を持つリクエストの場合、ブラウザはフロントエンドの JavaScript コードに、もし
Access-Control-Allow-Origin
ヘッダーが
*
. その代わりに、この場合の値はあなたのフロントエンド・コードのオリジンと正確に一致しなければなりません。
http://127.0.0.1:3000
.
参照 認証されたリクエストとワイルドカード を、MDN HTTP アクセス制御 (CORS) の記事で紹介しています。
リクエストを送信するサーバを制御している場合、このケースに対処する一般的な方法は、サーバ側で
Origin
リクエストヘッダを作成し、それを echo/reflect して
Access-Control-Allow-Origin
レスポンスヘッダを生成することができます(例:nginx)。
add_header Access-Control-Allow-Origin $http_origin
しかし、これは単なる例です。他の(ウェブ)サーバーシステムでも、同様の方法でオリジン値をエコーすることができます。
<ブロッククオート
Chromeを使用しています。また、そのChrome CORS Pluginを使用してみました。
そのChrome CORSプラグインは、どうやら単純に考えても
Access-Control-Allow-Origin: *
ヘッダをブラウザが見るレスポンスに追加します。もしこのプラグインがもっと賢かったら、この偽の
Access-Control-Allow-Origin
レスポンスヘッダを、フロントエンドの JavaScript コードの実際のオリジンに設定します。
http://127.0.0.1:3000
.
だから、テスト用でもそのプラグインを使うのは避けてください。邪魔になるだけです。ブラウザがフィルタリングしていない状態で、サーバからどのようなレスポンスが返ってくるかをテストするには
curl -H
と同じです。
フロントエンドのJavaScriptのコードとしては
fetch(…)
のリクエストは、質問の中にあります。
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
これらの行を削除してください。その
Access-Control-Allow-*
ヘッダーは
レスポンス
ヘッダを生成します。リクエストでは決して送らないようにしましょう。ブラウザがプリフライトを行うきっかけになるだけの効果しかありません。
関連
-
親子コンポーネント通信を解決する3つのVueスロット
-
[解決済み】 `string.split is not a function` というエラーの原因は何ですか?
-
[解決済み] Access-Control-Allow-Originヘッダーはどのように機能するのですか?
-
[解決済み] 私のJavaScriptコードは "No 'Access-Control-Allow-Origin' header is present on requested resource "というエラーを受け取りますが、Postmanはそうならないのはなぜですか?
-
[解決済み] Access-Control-Allow-Origin複数オリジンのドメイン?
-
[解決済み] プリフライト要求に対する応答がアクセス制御チェックを通過しない
-
[解決済み] file:// URLから実行されるアプリケーションのリクエストで、"Origin null is not allowed by Access-Control-Allow-Origin" エラーが発生する。
-
[解決済み] CORSです。資格情報フラグが true の場合、Access-Control-Allow-Origin でワイルドカードを使用できない。
-
[解決済み】Access-Control-Allow-OriginでOriginが許可されない。
-
[解決済み】「アクセス制御-許可-オリジン」がない - Node / Apacheのポートの問題
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Vueの要素ツリーコントロールに破線を追加する説明
-
vueにおけるv-forループオブジェクトのプロパティ
-
vueにおけるfilterの適用シーンについて解説します。
-
vueのプロジェクトでモックを使用する方法を知っていますか?
-
Vueのフォームイベントのデータバインディングの説明
-
[解決済み】Uncaught SyntaxError: JSONの位置0に予期しないトークンuがあります。
-
[解決済み】「X-Frame-Options」を「SAMEORIGIN」に設定したため、フレームでの表示を拒否された。
-
[解決済み】ERROR エラーです。スイッチのname属性が指定されていないフォームコントロールの値アクセッサがない
-
OSSアップロードエラーを解決する: net::ERR_SSL_PROTOCOL_ERROR
-
jq は html ページとデータを動的に分割する。