個人的備忘録：Go言語でCORSを理解する：フロントエンドの通信テストをやってみた

## はじめに
Web開発をしていると、異なるオリジン（ドメインやポートが異なるサイト）からAPIを呼び出すことがあります。

:::note info
**しかし、ブラウザのセキュリティ機能により、CORS (Cross-Origin Resource Sharing) の設定がないとアクセスが制限されてしまいます。**
:::

この記事では、Go言語を使って簡単にCORSを有効にし、ブラウザからAPIを呼び出せるようにする方法を紹介します。

## 1. 必要なライブラリをインストール

Goでは、プロジェクトディレクトリ内でモジュールを管理する必要があります。まずは、Goモジュールを初期化し、CORSライブラリをインストールします。

```sh
go mod init myproject
go get github.com/rs/cors
```

**実際のターミナル画面**

![Screenshot 2025-02-17 at 13.18.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/f599cfec-76a7-4307-b209-5f981728b709.png)


## 2. Goで簡単なHTTPサーバーを作成

以下のコードで簡単なGoのHTTPサーバーを作成します。このサーバーは、`/api/data` というエンドポイントを持ち、CORSを有効にしています。

```go
package main

import (
    "encoding/json"
    "log"
    "net/http"

    "github.com/rs/cors"
)

// レスポンス用の構造体
type Response struct {
    Message string `json:"message"`
}

func main() {
    mux := http.NewServeMux()
    
    // APIエンドポイント
    mux.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
        response := Response{Message: "Hello, CORS!"}
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(response)
    })

    // CORSの設定
    handler := cors.New(cors.Options{
        AllowedOrigins:   []string{"*"}, // すべてのオリジンを許可
        AllowedMethods:   []string{"GET", "POST", "OPTIONS"},
        AllowedHeaders:   []string{"Content-Type"},
    }).Handler(mux)

    log.Println("Server is running on port 5000")
    http.ListenAndServe(":5000", handler)
}
```

このコードを `server.go` というファイル名で保存します。

## 3. フロントエンドを作成

次に、CORSの動作を確認するための簡単なHTMLページを作成します。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CORS テスト</title>
</head>
<body>
    <h1>CORS テスト</h1>
    <button onclick="fetchData()">データ取得</button>
    <p id="result"></p>

    <script>
        function fetchData() {
            fetch('http://127.0.0.1:5000/api/data')
                .then(response => response.json())
                .then(data => {
                    document.getElementById('result').innerText = data.message;
                })
                .catch(error => console.error('Error:', error));
        }
    </script>
</body>
</html>
```

このHTMLファイルを `index.html` として保存します。

## 4. Goサーバーを起動

ターミナルでGoサーバーを起動します。

```sh
go run server.go
```

起動すると、以下のようなメッセージが表示されます。

```
Server is running on port 5000
```

## 5. 動作確認

1. `index.html` をブラウザで開きます。
2. 「データ取得」ボタンを押します。
3. `Hello, CORS!` のメッセージが表示されれば成功です。

**実際のブラウザ画面**

![Screenshot 2025-02-17 at 13.06.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/aea8095f-c5bb-41da-9c1b-6d1988e2ff76.png)

**サーバー画面**

![Screenshot 2025-02-17 at 13.47.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/091ce8f5-c573-4b30-a80f-550b93e19cfb.png)


## 6. CORSの制限をカスタマイズ

すべてのオリジンを許可するのではなく、特定のオリジンのみ許可することも可能です。

```go
handler := cors.New(cors.Options{
    AllowedOrigins:   []string{"http://example.com"}, // 特定のオリジンのみ許可
    AllowedMethods:   []string{"GET", "POST", "OPTIONS"},
    AllowedHeaders:   []string{"Content-Type"},
}).Handler(mux)
```

これにより、`http://example.com` からのリクエストのみ許可されます。

## まとめ

- `github.com/rs/cors` を使えば、Goでも簡単にCORSを設定できる。
- フロントエンドからAPIを呼び出してCORSを確認できる。
- CORSの設定をカスタマイズして、特定のオリジンのみ許可可能。

この方法を使えば、CORSに悩まされることなく開発を進められます。**ぜひ試してみてください！**