HTTPカスタムヘッダーを追加してクライアントとサーバー間でデータをやり取りするときのCORS設定
はじめに
HTTPリクエスト時にカスタムヘッダーを追加してクライアントとサーバー間でデータをやりとりしたい場合に必要なCORS設定についてまとめました。
この記事が参考になるかもしれない人
- クライアント側でカスタムヘッダーに値をセットして、サーバー側からアクセスしたい
- サーバー側でカスタムヘッダーに値をセットして、クライアント側からアクセスしたい
この記事では触れないこと
- CORS(Cross-Origin Resource Sharing)の説明や仕組み
- プリフライトリクエストと単純リクエスト
結論
- クライアント側でカスタムヘッダーに値をセットして、サーバー側からアクセスしたい
CORS設定のAccess-Control-Allow-Headers
に追加したいヘッダーを設定 - サーバー側でカスタムヘッダーに値をセットして、クライアント側からアクセスしたい
CORS設定のAccess-Control-Expose-Headers
に追加したいヘッダーを設定
クライアント側でカスタムヘッダーに値をセットして、サーバー側からアクセスしたい
必要なCORS設定:Access-Control-Allow-Headers
Access-Control-Allow-Headers
の設定が抜けていると、セキュアでないヘッダーが含まれていると判断されてサーバー側でリクエストが拒否されてしまいます。
CORSのデフォルト設定で許可されているヘッダーは Accept
, Accept-Language
, Content-Language
,Content-Type
です。
これ以外のヘッダーを扱いたい場合はAccess-Control-Allow-Headers
に追加する必要があります。例えばよく利用されそうなAuthorization
もAccess-Control-Allow-Headers
に含める必要があります。ちなみにAuthorization
はAccess-Control-Allow-Headers: *
で表すことができない(ワイルドカードに含まれない)ので明示する必要があります。
以下はソースコードのイメージです。
my-allow-header
, x-api-key
というヘッダーをセットしてクライアントからリクエストしています。
// クライアント側からカスタムヘッダーをセットしてリクエスト
const url = 'http://localhost:8080/test';
const res = await axios.post(
url,
{
param: 'param',
},
{
headers: {
'my-allow-header': 'myHeader',
'x-api-key': 'MyAPIKey',
},
},
);
サーバー側はmy-allow-header
, x-api-key
をAccess-Control-Allow-Headers
に追加しています。
// サーバー側のCORS設定
func Cors() gin.HandlerFunc {
config := cors.DefaultConfig()
// Access-Control-Allow-Originの設定
config.AllowOrigins = strings.Split(os.Getenv("CORS_ALLOW_ORIGINS"), ",")
// Access-Control-Allow-Headersの設定
config.AllowHeaders = []string{"Content-Type", "Authorization", "my-allow-header","x-api-key"}
return cors.New(cors.Config(config))
}
許可されていないヘッダーを含むリクエストを送信した場合、ブラウザの検証ツールにはこのように表示されています。
Chromeの検証ツールで確認した場合
サーバー側でカスタムヘッダーに値をセットして、クライアント側からアクセスしたい
必要なCORS設定:Access-Control-Expose-Headers
Access-Control-Expose-Headers
の設定が抜けているとクライアントからカスタムヘッダーにアクセスすることができません。
クライアントがデフォルトでアクセスできるヘッダーは Cache-Control
、Content-Language
、Content-Length
、Content-Type
、Expires
、Last-Modified
、Pragma
です。
これ以外のヘッダーにアクセスしたい場合はAccess-Control-Expose-Headers
に列挙する必要があります。Access-Control-Allow-Headers
と同じく、Authorization
はワイルドカードの対象にならないので明示する必要があります。
以下はソースコードのイメージです。
サーバー側のCORS設定で Access-Control-Expose-Headers
にx-my-expose-header
ヘッダーを追加します。
// サーバー側のCORS設定
func Cors() gin.HandlerFunc {
config := cors.DefaultConfig()
// Access-Control-Allow-Originの設定
config.AllowOrigins = strings.Split(os.Getenv("CORS_ALLOW_ORIGINS"), ",")
// Access-Control-Expose-Headersの設定
config.ExposeHeaders = []string{"x-my-expose-header"}
return cors.New(cors.Config(config))
}
ヘッダーにx-my-expose-header: my, expose, header
をセットしてリクエストしてみます。
// カスタムヘッダーを追加して値をセット
func SetMyHeader() gin.HandlerFunc {
return func(c *gin.Context) {
header := c.Writer.Header()
header["x-my-expose-header"] = []string{"my", "expose", "header"}
}
}
クライアント側ではカスタムヘッダーx-my-expose-header
にアクセスするだけです。
// フロントエンド側でカスタムヘッダーにアクセス
const url = 'http://localhost:8080/get-test';
const response = await axios.get(url);
console.log(response.headers);
const result = response.headers['x-my-expose-header']
レスポンスヘッダーをconsole.log
で出力してみると、x-my-expose-header
が存在していることが確認できます。
クライアント側でちゃんとヘッダーにアクセスできることを確認してみる
まとめ
HTTPリクエスト周りで変更を加えたい&期待した挙動にならないときはCORSの設定を確認!
参考
Discussion