背景
HTML/JavaScript/TypeScriptのダウンロード元と Ajaxでのアクセス先が異なる場合、Cross Resource Origin Sharing(以下CORSと略)ポリシーに従う必要があります。AjaxやCORSについての詳細はいろいろなところで説明されているので、ここでは割愛します。
Go+GinでのCORS対応の実装についてです。
前提
使用するソフトウェアのバージョンは以下のとおりです。
- Go : 1.20
- Gin : 1.9.0
また、すべてのアクセス先に対してCORSアクセスを許可する設定であるAccess-Control-Allow-Originヘッダへの"*"の設定ではなく、特定のアクセス先に対してのみ許可するものとします。
gin-contrib/cors
最初に見つけたのが「gin-contrib/cors」です。Ginの公式なCORSのパッケージのようです。ドキュメントはこちら。スニペットを見る限り使い方も簡単で、Ginのミドルウェアとして設定するだけです。
しかし「Canonical example」のスニペットを参考に実装してみたのですが、まったくCORSポリシーを解決できませんでした。OPTIONSリクエストに対して、レスポンスヘッダにはAccess-Control-Allow-Originヘッダが付いていません。しばらく設定を変えたりして試してみたのですが、全く解決できませんでした。
この状況をググってみて見つかったのがStackOverflowの記事「Go gin framework CORS」です。質問者はGoの標準ライブラリのみを使用していますが、OPTIONSに続くアクセスが発生せず、期待動作しないと言っています。
回答を見ると複数パターンあるようです。
- Goの標準ライブラリのみで実装の修正。質問者はこれで解決したもよう。
- gin-contrib/corsの使用を勧めるもの。これで動いたといっているのは1名のみ。
- rs/corsを勧めるもの。
- 独自ライブラリを勧めるもの。
自分の使っているGo/Ginのバージョンに比べて、gin-contrib/corsの最新リリースは2022/07/05なので幾分か古く、そのためGo/Ginの更新について行っていない可能性があります。Go/Ginのバージョンダウンまでして確認するほどgin-contrib/corsにこだわることもないので、このパッケージは諦めました。
標準ライブラリでの実装
変なライブラリを入れたくないので、結局標準ライブラリのみで実装することにしました。実際にCORSを解決できた最小限の実装が以下です。Ginのミドルウェアにしています。
func main() {
router := gin.Default()
router.Use(corsSetting)
// リクエストハンドラを設定 router.GET(...) etc.
}
func corsSetting(ginctx *gin.Context) {
// リクエスト元の確認
requestheader := ginctx.Request.Header
requestorigin := requestheader.Get("origin")
if リクエストの確認 {
// レスポンスヘッダの設定
responseheader := ginctx.Writer.Header()
responseheader.Set("Access-Control-Allow-Origin", requestorigin)
responseheader.Set("Access-Control-Allow-Headers", "Content-Type")
}
}
OPTIONSに続くアクセスのために、Access-Control-Allow-Headersレスポンスヘッダに"Content-Type"を設定しています。
0 件のコメント:
コメントを投稿