質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

CORS

CORSとはCross-Origin Resource Sharingの頭文字をとったもので、ブラウザがオリジン以外のサーバからデータを取得するシステムのことです。

Q&A

1回答

5086閲覧

Angualr の express で CORS 許可ができない

to33y

総合スコア10

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

CORS

CORSとはCross-Origin Resource Sharingの頭文字をとったもので、ブラウザがオリジン以外のサーバからデータを取得するシステムのことです。

0グッド

1クリップ

投稿2019/03/14 09:06

編集2019/03/14 23:21

前提・実現したいこと

Angular (v7) + Express (v4) で Web アプリをローカルマシンで開発しています。

OAuth を利用した認証付きのサイトにするために、 CORS に対応したロジックにしようとしており、
認証に関わる API が呼ばれたら OAuth の認証ページにリダイレクトする機構にしようとしています。

ひとまずは、特定の API が呼ばれた時に、 一旦 OAtuh とは全く関係無い別のよく知られたサイト (今回は Yahoo Japan に飛ばそうとしてます。) にリダイレクトだけさせてみようとしているのですが、
どうしても Chrome のコンソールで以下のエラーが出力されて、リダイレクト先に遷移が行われません。

(尚、認証をしなければ、既存の内部の API 通信処理は問題なく意図した動作ができることを確認しており、あとは認証機構だけ入れれば完了という状態になっています。)

発生している問題・エラーメッセージ

動作確認 Web ブラウザは Chrome です。

ブラウザの開発者ツール「Console」の結果

ブラウザコンソールに以下のコンソールログが吐かれてます。

  • Error ログ
Access to XMLHttpRequest at 'https://www.yahoo.co.jp/' (redirected from 'http://localhost:3000/api/auth') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • たて続けに出ている Warn ログ
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://www.yahoo.co.jp/ with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
ブラウザの開発者ツール「Network」の結果

text

1【General】 2Request URL: http://localhost:3000/api/auth 3Request Method: GET 4Status Code: 302 Found 5Remote Address: [::1]:3000 6Referrer Policy: no-referrer-when-downgrade 7 8【Response Headers】 9Access-Control-Allow-Origin: * 10Connection: keep-alive 11Content-Length: 46 12Content-Type: text/plain; charset=utf-8 13Date: Thu, 14 Mar 2019 08:54:36 GMT 14Location: https://www.yahoo.co.jp/ 15Vary: Accept 16X-Powered-By: Express 17 18【Request Headers】 19Accept: application/json, text/plain, */* 20Accept-Encoding: gzip, deflate, br 21Accept-Language: ja,en-US;q=0.9,en;q=0.8 22Connection: keep-alive 23Content-Type: application/json 24Host: localhost:3000 25Referer: http://localhost:3000/ 26User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36

text

1【General】 2Request URL: https://www.yahoo.co.jp/ 3Request Method: OPTIONS 4Status Code: 200 5Remote Address: 183.79.250.251:443 6Referrer Policy: no-referrer-when-downgrade 7 8【Request Headers】 9Provisional headers are shown 10Access-Control-Request-Headers: content-type 11Access-Control-Request-Method: GET 12Origin: http://localhost:3000 13Referer: http://localhost:3000/ 14User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36

該当のソースコード

クライアント側

クライアントの API 呼び出しは以下のサービスクラスで実行。CORS の対応は、クライアント側は特に無い認識です。

ts

1import { Injectable } from '@angular/core'; 2import { HttpClient, HttpHeaders, HttpParams, HttpResponse, HttpErrorResponse } from '@angular/common/http'; 3 4@Injectable({ providedIn: 'root' }) 5export class HttpService { 6 7 constructor(protected http: HttpClient) { } 8 9 // API 呼出メソッド (GET) 10 private async get(): Promise<any> { 11 try { 12 const url = 'http://localhost:3000/api/auth'; 13 const httpParams: HttpParams = new HttpParams(); 14 15 // HTTP通信 実行 16 const response = await this.http.request<Res>(method, url, { 17 headers: new HttpHeaders({ 'Content-Type': 'application/json' }), 18 responseType: 'json', 19 params: httpParams 20 }).toPromise(); 21 22 return { ok: true, status: 200, body: response }; 23 } catch (error) { 24 return { ok: false, body: undefined }; 25 } 26 } 27}

サーバ側

こっちで CORS 対応を頑張れば良い認識。
以下の3種類のソースで試してみてますが、いずれも全く同じエラーでうまくいきません。

パターン1:ワイルドカードで全て CORS 許可

レスポンスヘッダは、ベタ書き

ts

1import * as express from 'express'; 2import * as bodyParser from 'body-parser'; 3import { join } from 'path'; 4 5const app = express(); 6 7// CORS 対応 (ベタ書き) 8app.use((req, res, next) => { 9 res.header('Access-Control-Allow-Origin', '*'); 10 res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, application/json, Accept, x-client-key, x-client-token, x-client-secret, Authorization'); 11 res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 12 next(); 13}); 14 15// API ルーティング提供 (一応 ボディパーサも対応) 16app.use(bodyParser.urlencoded({ extended: true })); 17app.use(bodyParser.json({ limit: '100kb' })); 18app.get('/api/auth', (req, res) => { 19 res.redirect('https://www.yahoo.co.jp/'); 20}); 21 22// クライアント静的ファイル提供 23app.use(express.static(join(process.cwd(), 'dist/my-web-app'))); 24 25// アプリ起動 26app.listen(3000);
パターン2:Origin を2サイト明示して、 更にヘッダに "Credentials: True" を設定

こちらもレスポンスヘッダは、ベタ書き

ts

1import * as express from 'express'; 2import * as bodyParser from 'body-parser'; 3import { join } from 'path'; 4 5const app = express(); 6 7// CORS 対応 (ベタ書き) 8app.use((req, res, next) => { 9 res.header('Access-Control-Allow-Origin', 'http://localhost:3000, https://www.yahoo.co.jp/'); 10 res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, application/json, Accept, x-client-key, x-client-token, x-client-secret, Authorization'); 11 res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 12 res.header('Access-Control-Allow-Credentials', 'true'); 13 next(); 14}); 15 16app.use(bodyParser.urlencoded({ extended: true })); 17app.use(bodyParser.json({ limit: '100kb' })); 18app.get('/api/auth', (req, res) => { 19 res.redirect('https://www.yahoo.co.jp/'); 20}); 21 22app.use(express.static(join(process.cwd(), 'dist/my-web-app'))); 23 24app.listen(3000);
パターン3:npm パッケージ「cors」を利用

ts:server.ts

1import * as cors from 'cors'; // 追加 2import * as express from 'express'; 3import * as bodyParser from 'body-parser'; 4import { join } from 'path'; 5 6const app = express(); 7 8// CORS 対応 (全て CORS 許可する設定で利用) 9app.use(cors()); 10 11app.use(bodyParser.urlencoded({ extended: true })); 12app.use(bodyParser.json({ limit: '100kb' })); 13 14app.get('/api/auth', (req, res) => { 15 res.redirect('https://www.yahoo.co.jp/'); 16}); 17 18app.use(express.static(join(process.cwd(), 'dist/my-web-app'))); 19 20app.listen(3000);

上記の3パターンを試しても、CORS 対応はできず、他のネット記事をみても同じような対応しか見当たらない状況です。

どなたか原因または解消方法がわかる方はいますでしょうか?

補足情報(FW/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

私もcorsはまだまだ悩みながら対応している状態なので、的はずれな回答をしていたらすみません。

今テストされているケースですと、

Yahoo Japan側が Access-Control-Allow-Origin に localhost:3000を追加してくれないと、
CORSのエラーで引っかかるのではないかと思いました。

投稿2019/03/18 12:06

motsu3DJ

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問