こうこく
作 ▸
改 ▸

Axiosでレスポンスヘッダが取得できなかった (CORSなAPI)

標準的なレスポンスヘッダ以外の場合は、APIが返すレスポンスヘッダに Access-Control-Expose-Headers: ${レスポンスヘッダ名} を追加する必要がある。

axios 0.19.0

画面とAPIが別のドメインにあるWebアプリを作ってました。

以下、ここでは画面側URLが https://mywebapp.com、API側URLが https://api.mywebapp.com とします。

そのAPIがカスタムレスポンスヘッダ X-Piyopiyo を返す仕様だったのですが、これがAxiosのレスポンスオブジェクトになぜか入ってこなくて、取得できませんでした。

import axios from 'axios';

const params = {
  age: 14
};
const options = {
  headers: { 'Content-Type': 'application/json;charset=utf-8' }
};

axios.post('https://api.mywebapp.com', params, options)
  .then(res => {
    console.log(res.headers);
  })
  .catch(err => {
    // 略
  });
コンソール出力
headers:
  cache-control: "max-age=999"
  content-length: "9999"
  content-type: "application/json"

res.headersX-Piyopiyo がありません。

不可解だったのは、ブラウザの開発者ツールのレスポンスにはちゃんと X-Piyopiyo が表示されてるところでした。JavaScriptの中からだけ、アクセスできないみたいです。

ググってたら以下のページを見つけました。

Axios get access to response header fields - Stack Overflow

どうやらCORSなWebAPIの場合、ブラウザ側で扱えるレスポンスヘッダの名称を、Access-Control-Expose-Headers ヘッダで明示的に指定する必要があるようです。

Cache-Control とか Content-Type のような一般的なレスポンスヘッダならば不要みたいですが、今回は自分で定義したレスポンスヘッダなので必要でした。

ここで書いてる例の場合、WebAPI側のレスポンスヘッダに Access-Control-Expose-Headers を追加して以下のようにしたら、Axiosの res.headersX-Piyopiyo が入ってくるようになりました。

WebAPI側のレスポンスヘッダ
Content-Type: application/json;charset=utf-8
Access-Control-Allow-Origin: https://mywebapp.com
Access-Control-Expose-Headers: X-Piyopiyo

なお、Preflight (OPTIONSメソッド) のレスポンスヘッダには、特に Access-Control-Expose-Headers は設定しなくて大丈夫なようです。

この記事に何かあればこちらまで (非公開)