Go言語でのCORS対応の基礎と安全な設定方法
生徒
「先生、GoでWeb APIを作ったんですが、他のサイトからリクエストが弾かれてしまいます。どうすればいいですか?」
先生
「それはCORSの問題ですね。CORSとは、異なるドメインからのアクセスを制御する仕組みです。Cross-Origin Resource Sharingの略で、Webブラウザがセキュリティ上の理由で制限しているものです。」
生徒
「具体的にはどうやって対応するんですか?」
先生
「Goでは、HTTPヘッダにAccess-Control-Allow-Originを追加することで対応できます。また、サードパーティのライブラリを使うと簡単に設定できます。」
1. CORSとは?
CORSは、Webブラウザが異なるオリジン(ドメイン、ポート、プロトコルの組み合わせ)からのリクエストを制限する仕組みです。 もともとブラウザには「同一オリジンポリシー」という基本ルールがあり、勝手に別ドメインの情報へアクセスできないようにしています。 その制限を、決めた条件の範囲内で“許可するための仕組み”がCORSだと考えると分かりやすいです。
例えば、https://example.comの画面(フロント側)が、
https://api.example2.comのAPI(サーバー側)へデータを取りに行くとき、
何も設定しないとブラウザが「安全確認ができないので止めます」と判断して弾くことがあります。
このとき、サーバーが「このオリジンからのアクセスならOK」とHTTPヘッダで伝えることで、ブラウザは安心して通信を続けられます。
初心者の方は、CORSを「外部サイトからのアクセスに対して、通していい相手だけ通す入場チェック」のようなものだと思ってください。 設定が合っていないと、サーバーは動いているのにブラウザ側だけエラーになることもあるので、まずは仕組みを押さえておくのが近道です。
// イメージ:サーバーが許可を出すと、ブラウザが通信を続けられる
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "https://example.com")
w.Write([]byte("CORSの基本イメージ"))
}
このように、CORSは「ブラウザが安全のために止める動き」と「サーバーが許可を示すヘッダ」がセットで成り立っています。 まずは“別オリジンの通信にはルールがある”という点を覚えておくと、次の設定の話もスムーズにつながります。
2. 基本的なCORS対応
GoでCORSを有効にするもっとも基本的な方法は、
HTTPレスポンスヘッダに Access-Control-Allow-Origin を追加することです。
これは「どのオリジンからのアクセスを許可するか」をブラウザに伝える役割を持っています。
まずは、このヘッダがCORS対応の出発点になると覚えておきましょう。
たとえば、すべてのオリジンからのアクセスを一時的に許可したい場合は、
値に * を指定します。
開発中に動作確認をしたいときなど、原因切り分けの目的で使われることが多い設定です。
プログラミング未経験の方は「とりあえず全部OKにする設定」と考えると分かりやすいです。
func handler(w http.ResponseWriter, r *http.Request) {
// すべてのオリジンからのアクセスを許可
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Write([]byte("CORS対応テスト"))
}
このコードでは、ブラウザに対して 「どのサイトから来たリクエストでも受け付けます」 という意思表示をしています。 そのため、CORSエラーが原因で画面が動かなかった場合は、 まずこの形で通信できるか確認するのが定番です。
ただし、* を使うと本当にすべてのサイトからアクセスできてしまいます。
本番環境でこの設定を使い続けるのは危険なので、
動作確認ができたら、許可するオリジンを絞る設定に切り替えることが重要です。
ここでは「CORS対応の基本形」として、この仕組みをしっかり理解しておきましょう。
3. サードパーティライブラリで簡単に設定
CORS対応は手書きでもできますが、実務では「設定漏れ」や「書き忘れ」を避けるために、
サードパーティのCORSライブラリを使うことがよくあります。
Go言語では、github.com/rs/cors が定番で、許可するオリジンやメソッドをまとめて管理できるのが強みです。
初心者の方は「CORS用の便利な部品を借りて、設定を整理しやすくする方法」と思うとイメージしやすいです。
使い方はシンプルで、まず通常どおりに http.NewServeMux() でルーティングを作り、
その後にCORSの設定をしたハンドラで包みます。
こうすると、個々のハンドラに毎回ヘッダを書く必要がなくなり、設定を一か所に集約できます。
import (
"net/http"
"github.com/rs/cors"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("CORS設定済み"))
})
// CORSの許可ルールをまとめて定義する
c := cors.New(cors.Options{
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET", "POST"},
})
// ルーティング全体をCORS対応のハンドラで包む
handler := c.Handler(mux)
http.ListenAndServe(":8080", handler)
}
この設定では、https://example.com からのアクセスだけを許可し、
HTTPメソッドは GET と POST に限定しています。
それ以外のサイトや不要なメソッドはブラウザ側でブロックされやすくなるため、
「必要な範囲だけ許可する」というCORSの基本方針にも合っています。
まずはライブラリで動かしてみると、CORSの全体像がつかみやすくなります。 そのうえで「どのオリジンを許可するか」「どのメソッドを通すか」を少しずつ調整していくと、 GoでのWeb API開発でも自然に安全なCORS設定へ近づけられます。
4. 安全なCORS設定のポイント
- 必要なオリジンのみを
AllowedOriginsに指定する - 不要なHTTPメソッドは許可しない
- Cookieを利用する場合は
AllowCredentials: trueを設定し、*を使わない
これにより、意図しない外部サイトからの不正アクセスを防ぎ、セキュリティを保ちながらCORS対応できます。
5. 実際の利用ケース
例えば、フロントエンドがhttps://myfrontend.com、バックエンドがhttps://myapi.comの構成の場合、CORSを正しく設定することで、フロントエンドから安全にAPIにアクセスできるようになります。間違って*を設定すると、他の悪意あるサイトからもAPIにアクセスできてしまうため注意が必要です。
6. プリフライトリクエストとは何か
CORS対応を進めていくと、「プリフライトリクエスト」という言葉を目にすることがあります。 これは、ブラウザが実際のリクエストを送信する前に、 「この操作をしても問題ありませんか?」とサーバーに事前確認を行う仕組みです。 特に、POSTやPUT、DELETEといった操作や、カスタムヘッダを含むリクエストでは自動的に発生します。
GoでAPIを作っている場合、プリフライトリクエストはHTTPメソッドが
OPTIONS として送られてきます。
このリクエストに正しく応答しないと、本来のAPI処理が実行される前に
ブラウザ側で通信が止められてしまいます。
初心者の方は「本番リクエストの前にチェック用の通信がある」と覚えておくと理解しやすいです。
func handler(w http.ResponseWriter, r *http.Request) {
// プリフライトリクエストへの対応
if r.Method == http.MethodOptions {
w.Header().Set("Access-Control-Allow-Origin", "https://example.com")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.WriteHeader(http.StatusOK)
return
}
w.Write([]byte("通常のAPIレスポンス"))
}
このようにOPTIONSリクエストを明示的に処理することで、 ブラウザとの通信がスムーズになり、CORSエラーを防ぎやすくなります。
7. Cookieや認証情報を使う場合の注意点
ログイン状態を維持するAPIや、セッションを使った認証を行う場合、 Cookieを伴うCORS通信が必要になることがあります。 このとき、単にオリジンを許可するだけでは不十分で、 追加の設定が必要になります。
具体的には、Access-Control-Allow-Credentials を
true に設定し、許可するオリジンを明示的に指定します。
この場合、* を使うことはできません。
セキュリティ上の理由から、ブラウザが厳しく制限しているためです。
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "https://example.com")
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Write([]byte("認証付きCORS対応"))
}
認証情報を扱うAPIでは、CORS設定のミスが セキュリティ事故につながる可能性があります。 必要な範囲だけを許可する意識を持つことが重要です。
8. 開発環境と本番環境で設定を分ける考え方
CORS設定は、開発環境と本番環境で内容が変わることがよくあります。 開発中はローカル環境や複数のURLからアクセスする必要があるため、 比較的ゆるい設定を使うケースが多いです。 一方で、本番環境では不要なオリジンをすべて遮断することが求められます。
Goでは、環境変数や設定ファイルを使って、 環境ごとに許可するオリジンを切り替える方法が一般的です。 これにより、開発のしやすさと本番環境の安全性を両立できます。
allowedOrigin := "https://example.com"
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", allowedOrigin)
w.Write([]byte("環境に応じたCORS設定"))
}
最初から完璧な設定を目指す必要はありませんが、 「環境によってCORSの考え方が変わる」という点を理解しておくと、 実務でのトラブルを大きく減らすことができます。
まとめ
CORS対応の全体像を振り返る
この記事では、Go言語を使ったWebアプリやWeb API開発において避けて通れない CORS対応について、基礎から実務で役立つ考え方まで順を追って解説してきました。 CORSは、ブラウザが安全性を守るために用意している仕組みであり、 サーバー側が意図しないアクセスを防ぐための重要な役割を担っています。 単にエラーを消すための設定ではなく、 「どのサイトから、どの操作を許可するのか」を明確にするためのルールだと理解することが大切です。
基本としては、HTTPレスポンスヘッダに
Access-Control-Allow-Origin を設定することで、
ブラウザに対して「このリクエストは許可してよい」と伝えます。
しかし、すべてのオリジンを許可する * の指定は手軽な反面、
意図しない外部サイトからのアクセスを許してしまう可能性があります。
学習段階では便利でも、実際の運用では慎重に扱う必要があります。
そこで紹介したのが、Go向けのサードパーティライブラリを使ったCORS設定です。 ライブラリを使うことで、許可するオリジンやHTTPメソッドを明確に指定でき、 コードの可読性も高まります。 特にフロントエンドとバックエンドを分離した構成では、 CORSの正しい設定がないとAPI通信そのものが成り立ちません。 その意味でも、CORSはWeb開発の基礎知識として早めに理解しておく価値があります。
最低限覚えておきたいCORS設定サンプル
func handler(w http.ResponseWriter, r *http.Request) {
// 特定のオリジンのみ許可する例
w.Header().Set("Access-Control-Allow-Origin", "https://example.com")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST")
w.Write([]byte("CORS設定済みレスポンス"))
}
このように、許可するオリジンやメソッドを明示するだけでも、 セキュリティと利便性のバランスは大きく向上します。 CORS対応は「とりあえず動かす」ことよりも、 「なぜこの設定が必要なのか」を理解しながら進めることが重要です。 それが結果的に、トラブルの少ない安定したWeb API設計につながります。
生徒
「CORSって、最初はエラーの原因くらいにしか思っていませんでしたけど、 実はWeb全体の安全を守るための仕組みなんですね。」
先生
「その通りです。CORSはブラウザ側の制限ですが、 サーバーが正しくルールを示すことで初めて意味を持ちます。 何でも許可する設定は楽ですが、長い目で見ると危険です。」
生徒
「なるほど……。 フロントエンドとバックエンドを分ける構成だと、 CORSを理解していないと開発が止まってしまいそうですね。」
先生
「その通りです。 GoでAPIを作るなら、CORSは必須の知識です。 今日学んだように、許可するオリジンやメソッドを整理して考えれば、 難しいものではありません。」
生徒
「これからは、エラーが出たときも 『なぜCORSで止められているのか』を考えられそうです。 安全な設定を意識してAPIを作ってみます!」
先生
「それができれば十分です。 CORSを理解しているだけで、GoのWeb開発は一段レベルアップしますよ。」