Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Your API works in curl but not in the browser — that's CORS

2026年09月26日に「Dev.to」が公開したITニュース「Your API works in curl but not in the browser — that's CORS」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

ブラウザで異なるオリジンのAPIにアクセスすると、セキュリティ機能CORSにより通信がブロックされる。APIは正常でも、サーバー側で許可するオリジンを示すCORSヘッダーを設定し、事前確認(プリフライト)に対応する必要がある。

ITニュース解説

システムエンジニアを目指すあなたがAPI開発に携わる際、ある疑問に直面することがある。自分で作成したAPIをコマンドラインツールであるcurlでテストすると問題なく動作するのに、Webブラウザから呼び出すと「CORSポリシーによってブロックされました」といったエラーが出てしまう現象だ。これはCORS(Cross-Origin Resource Sharing)という仕組みによって引き起こされる。

まず、curlとWebブラウザの動作の違いを理解することが重要だ。curlは単純に指定されたURLへリクエストを送り、サーバーからの応答をそのまま利用者に返す。リクエストがどこから来たか、どのWebページがそれを開始したかといった概念を一切持たない。そのため、サーバーが応答を返せば、curlはそれを成功と判断する。

一方、Webブラウザはcurlとは異なり、セキュリティ上の重要な役割を担っている。ブラウザは、JavaScriptのコードがどのWebページ(オリジン)から実行され、どのAPI(異なるオリジン)にアクセスしようとしているかを常に把握している。例えば、http://localhost:5173というアドレスのWebページから、http://localhost:8080という異なるポートで動作するAPIにアクセスしようとする場合、ブラウザはこれを「異なるオリジンからのアクセス」と判断する。デフォルトでは、Webページは自身のオリジン、つまり同じドメイン、同じプロトコル、同じポート番号を持つサーバーにのみアクセスが許されている。

この厳格なルールは、ユーザーを悪意ある攻撃から守るために存在する。もしこの制限がなければ、あなたが訪問した悪意のあるウェブサイトが、あなたのブラウザに保存されている銀行サイトのクッキーを悪用し、気づかないうちに不正な送金リクエストをあなたの銀行APIに送信するといったことが可能になってしまう。CORSは、このようなセキュリティリスクからユーザーを保護するための重要なセキュリティメカニズムなのだ。

したがって、CORSは「このサーバーは、指定されたオリジンからのアクセスを許可します」という、サーバー側からの明示的な許可によって成立する。ここで二つの重要なポイントがある。第一に、アクセス許可はサーバーから発行されるものであり、フロントエンドのJavaScriptコードでCORS問題を解決しようとしても無意味だ。もしフロントエンドでCORSを解決すると謳う手法があれば、それは実際にはプロキシ(代理)を介してリクエストを転送しているに過ぎない。第二に、CORSポリシーを強制するのはWebブラウザであり、サーバーではない。そのため、ブラウザでエラーが表示されても、サーバーのログにはAPIが正常に応答した記録が残っていることがよくある。これは、サーバーは正常に応答を返したが、ブラウザがセキュリティポリシーに基づいてその応答をJavaScriptに渡さずに破棄したためだ。

CORSの動作には、「プリフライトリクエスト」という特別なステップが存在する。シンプルなGETリクエストの場合、ブラウザは直接リクエストを送信し、その応答に含まれるCORS関連のヘッダーをチェックして許可を得る。しかし、JSONデータを送信するPOSTリクエスト、PATCH、DELETE、あるいは認証ヘッダー(Authorizationヘッダーなど)を含むリクエストなど、より複雑なリクエストの場合、ブラウザは本番のリクエストを送信する前に、まずOPTIONSメソッドを使った「プリフライトリクエスト」をサーバーに送信する。このプリフライトリクエストでは、「私はこのオリジンからアクセスします。このメソッドを使いたいのですが、これらのヘッダーを送信したいのですが、許可されますか?」とサーバーに問い合わせる。サーバーは、このOPTIONSリクエストに対して、許可するオリジン、メソッド、ヘッダーなどを指定したCORSヘッダーを付けて応答しなければならない。もしサーバーがこのプリフライトリクエストに適切に応答しなければ、ブラウザは本番のリクエストを一切送信しない。多くの開発者がGETリクエストは動くのにPOSTリクエストが動かないと困惑するのは、このプリフライトリクエストの存在を知らないためだ。

CORS問題を解決するには、APIサーバー側でCORSミドルウェアを実装し、適切なHTTPヘッダーを応答に含める必要がある。例えばGo言語の場合、withCORSという関数でミドルウェアを実装する。この関数は許可されたオリジンのリストと次のHTTPハンドラを受け取り、まずリクエストヘッダーからOriginを取得し、それが許可されたオリジンの一つであるかを確認する。許可されている場合、Access-Control-Allow-Originヘッダーにリクエスト元のオリジンをセットする。これにより、複数のフロントエンドが同じAPIを利用できるようになる。また、VaryヘッダーにOriginを追加することは非常に重要だ。これは、応答の内容がリクエスト元のオリジンによって異なる場合があるため、キャッシュサーバーが誤って異なるオリジンに間違った応答を返さないようにするためだ。さらに、Access-Control-Allow-Methodsヘッダーで許可するHTTPメソッド(GET, POST, PATCH, DELETE, OPTIONSなど)を、Access-Control-Allow-Headersヘッダーで許可するリクエストヘッダー(Authorization, Content-Typeなど)を指定する。特にAuthorizationヘッダーをここに含め忘れると、認証トークンを送信するAPI呼び出しがすべて失敗することになるので注意が必要だ。Access-Control-Max-Ageヘッダーは、プリフライトリクエストの応答をブラウザがキャッシュする期間(秒単位)を指定する。これにより、同じリソースへの繰り返しのリクエストに対して、ブラウザが毎日プリフライトリクエストを送信するのではなく、一度だけ問い合わせれば済むようになり、パフォーマンスが向上する。

そして、リクエストのHTTPメソッドがOPTIONSである場合、それがプリフライトリクエストであるため、実際のAPIハンドラには到達させず、適切なCORSヘッダーを付けて204 No Contentステータスコードで応答を返す。これにより、ブラウザは本番リクエストを安全に送信できるようになる。

CORSの設定でよく見かける間違いに、Access-Control-Allow-Origin: *というワイルドカードを使用する方法がある。これはどんなオリジンからのアクセスも許可するという意味であり、開発中に一時的に使うには便利に思えるかもしれないが、セキュリティ上非常に危険であり、認証情報を含むリクエストではブラウザによって無視されるため、ほとんどの場合で適切ではない。代わりに、http://localhost:5173のような特定のオリジンを許可するように設定し、本番環境では実際のドメイン名を使用するように、環境変数などから許可オリジンのリストを読み込むべきである。

CORSの設定が正しく機能しているかを確認するには、ブラウザでのテストだけでなく、開発中にも積極的にテストを行うべきだ。curlコマンドを使って、自分でプリフライトリクエストをシミュレートできる。 curl -i -X OPTIONS localhost:8080/api/login -H 'Origin: http://localhost:5173' -H 'Access-Control-Request-Method: POST' このようにOPTIONSリクエストを送信し、サーバーからの応答に含まれるCORSヘッダーが期待通りであるかを確認することで、ブラウザがどのように振る舞うかを予測できる。さらに、許可されたオリジンだけでなく、許可されないオリジンからのリクエストが正しく拒否されるかを確認する単体テストを記述することも非常に重要である。これにより、意図せず全てのオリジンからのアクセスを許可してしまうといったセキュリティホールを防げる。

最後に、開発環境ではCORSが問題なく動作していたのに、本番環境にデプロイすると急に動かなくなるという状況も頻繁に発生する。これはたいていの場合、ALLOW_ORIGINSなどの環境設定がhttp://localhost:5173のままであり、本番環境のドメイン名に更新されていないことが原因だ。デプロイ時には、必ず本番環境のドメイン名がCORS設定に正しく反映されていることを確認する必要がある。

CORSはウェブ開発において避けて通れない重要な概念だ。その仕組みと設定方法を理解し、適切に実装することで、安全で機能的なウェブアプリケーションを構築できるようになる。

関連コンテンツ

関連IT用語