DrupalでCORS対応をしてAPIでアクセスできるようにしよう

この記事ではDrupal10でCORS対応を実施して、外部からAPIへアクセスできるようにする方法についてご紹介します。

この記事の内容

  • CORSとは
  • Drupal10におけるCORS設定
この記事を書いた人
  • 約5年間Drupal開発をおこなってきました
  • カスタムテーマ、カスタムモジュールを作って
    WEBサイトを構築できます。
  • 当ブログではDrupalを中心にWEB開発に関するTipsを発信

バックエンドにDrupalを採用したWEBサイトを構築中、異なるサーバー間の通信で開発作業が詰まってしまいました。
この記事ではそこで遭遇したエラーやその解消等を含めてCORS対応のやり方をご紹介します。

アプリケーションの(超)概要

目次

CORSとは

CORS(Cross-Origin Resource Sharing)とはオリジン間リソース共有と呼ばれ、
異なるオリジンに存在するリソース(ファイルやページ)にアクセスできるようにブラウザに教えてあげる仕組みです。

DrupalにおけるCORS

Drupalでは異なるサーバーからデータにアクセスされることを標準で無効化しています。

これはdefault.services.yml(or services.yml)で以下のように設定されています。

cors.config:
    enabled: false

このため外部のサーバーからDrupal APIを介してDrupal上のデータを使うためには、この設定を有効化する必要があります。

DrupalでCORSを有効化する

sites/default/services.ymlを次のように書き換えます

# Configure Cross-Site HTTP requests (CORS).
# Read https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
# for more information about the topic in general.
# Note: By default the configuration is disabled.
cors.config:
    # enabled: false # --- 修正前
    enabled: true # --- 修正後 
    # Specify allowed headers, like 'x-allowed-header'.
    allowedHeaders: []
    # Specify allowed request methods, specify ['*'] to allow all possible ones.
    allowedMethods: []
    # Configure requests allowed from specific origins. Do not include trailing
    # slashes with URLs.
    allowedOrigins: ['*']
    # Configure requests allowed from origins, matching against regex patterns.
    allowedOriginsPatterns: []
    # Sets the Access-Control-Expose-Headers header.
    exposedHeaders: false
    # Sets the Access-Control-Max-Age header.
    maxAge: false
    # Sets the Access-Control-Allow-Credentials header.
    supportsCredentials: false

こちらの設定でどのメソッドやオリジンを許可するかを設定しています。
以上の設定だと全てのメソッドやオリジンを許可する設定になっていますので本番環境で行うことは控えてください。
必ず要件に応じた設定をおこなってください。

なおservices.ymlが存在しない場合、default.services.ymlをコピーして作成します。

cp sites/default/default.services.yml sites/default/services.yml

私の場合はsites/defaultに書き込み権限がなかったのでchmodしましたが、
その辺は環境によっても異なるので適宜実施してください。

CORS対応で発生したエラーなど

ここでは前述のCORS対応を実施する中で遭遇したエラーやその対応方法をご紹介します。

Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

解決方法許可するリクエストヘッダーをDrupal側で設定する
エラーの詳細リクエストヘッダーに含まれるcontent-typeが許可されてない

解決方法の詳細

services.ymlで許可したいリクエストヘッダーを記載する

cors.config:
    enabled: true
    # Specify allowed headers, like 'x-allowed-header'.
    # allowedHeaders: [] # 修正前
    allowedHeaders: ['X-CSRF-Token','Content-Type'] # 修正後の実装例
  • services.yml作成時はこれが空なのでなにかしら記載する必要があります。
  • *(全てのリクエストヘッダー)が使用可能です。(安全にしたいならあまりオススメしない)
  • allowMethodsも同様です。

‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’.

解決方法postする内容からwithCredentials: trueを削除する
エラーの詳細Credentialsモードを有効にするならAccess-Control-Allow-Originに*は指定しないでね

解決方法の詳細

Drupal APIに対してPOSTリクエストを送った時に発生したのですが、
この時クライアント側ではwithCredentials: trueを設定していました。

あわせて読みたい

どうやらこれを有効にしているならワイルドカードは指定できないよ。というエラーですのでwithCredentials: trueを削除しました。

await axios.post(
   'Endpoint URL',
   values,
   {
       headers: headers,
       // withCredentials: true // ここを削除した
   },
);

withCredentials: true
この設定自体はCookieをHTTPヘッダに付ける設定(らしい)

さいごに

今回はDrupalが提供するAPIへ外部サーバーからアクセスできる方法(CORS対応)と、
トラブルシューティングについてご紹介しました。

バックエンドにDrupalを採用し、フロントエンドからAPIを介してDrupalにアクセスする場合に必要な対応かと思いますのでぜひ参考にしてみてください。

目次