Drupal 8 or 9 の 500 エラーページをカスタマイズする


Drupal 8 or 9 で致命的なエラーが発生した時に表示される 500エラーページをカスタマイズする方法を紹介します。

500エラーページとはこういうメッセージが表示されるやつです:

The website encountered an unexpected error. Please try again later.

選択肢

a) Drupal だけで対応する場合

  • Drupal 9.0.7 時点では、コアのエラー処理をカスタマイズする方法は用意されておらず、スマートな実現方法はない
  • エラーの発生場所、内容によってはカスタマイズが不可能な場合もある (settings.php でのエラーなど)

選択肢

  1. 実行時にエラーハンドラを独自のものに置き換える
    • この方法で実装された error_page モジュールが存在
    • コアのコードをコピペ & 修正してエラーハンドラをまるごと置き換える必要があり、コアのアップデートに追従できないリスクがある
  2. コアのエラーハンドラを修正する
    1. 自前で修正する
      • 奥の手
    2. Drupal.org の issue (Ability to Customize Core Error Message [#3108689] | Drupal.org) のパッチを利用する
      • ★ 次点でこれ

b) CDN などの上位層で対応する場合

  1. CDNで対応
  2. Apache でがんばる
    • mod_ext_filter を使えばできないことはないが、色々デメリットがあるため非現実的
    • フィルタプログラムを作る手間とかパフォーマンスへの影響とか

以下では、#3108689 のパッチを利用してDrupalだけで対応する方法について考えます。

a.2.2) #3108689 のパッチを利用する方法

CDNでの対応ができない場合は、次点でこれが一番マシだと思われます。

Drupal.orgで、500エラーページのメッセージをカスタマイズする機能を追加するissueが進行中で、
Ability to Customize Core Error Message [#3108689] | Drupal.org

パッチの内容には大きな問題はなさそうでですが、まだマージされていないため使うには自前でパッチを当てる必要があります。
また、issueに添付されている 3108689-51.patch のパッチは、drupal/core パッケージには存在しないファイル (sites/default/default.settings.php) のdiffが含まれるため、そのdiffを取り除いてから適用する必要があります。

(cweagans/composer-patches プラグインを使ってパッチを当てることを想定)

使い方

  1. #3108689 のパッチから不要な diff を削除したファイルをリポジトリに追加する
    • sites/default/default.settings.php のdiffを消す
    • 修正したパッチを [repo-root]/patches/drupal/core/3108689-51--mod.patch などに置く
  2. composer.jsonextra.patches.drupal/core にパッチのパスを追加
  3. composer install 実行
  4. settings.php$settings['custom_error_message'] にエラーページの内容 (HTML) を設定する

気をつけること

  • 完全に静的な HTML 文字列を $settings に設定する
    • CSSファイルなどへのURLも絶対URLで直接記述する
    • 内容を動的に変えることはできない
  • settings.php に直接HTMLを書く必要がある
    • HTMLファイルに分離すると必要ないときもファイル読み込みが発生してしまうため

使用例

composer.json
    "extra": {
        "patches": {
            "drupal/core": {
                "3108689 Ability to Customize Core Error Message": "patches/drupal/core/3108689-51--mod.patch"
            }
        },
settings.php
$settings['custom_error_message'] = <<<'HTML'
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>エラーです</title>
  <style>
  body {
    width: 400px;
    margin: 0 auto;
  }
  h1 {
    background-color: red;
    color: white;
  }
</style>
</head>
<body>
  <h1>エラーです</h1>
  <p>何かやばいエラーが発生しました。</p>
  <p>しばらく待ってから再読み込みしてみてください。</p>
  <p><a href="/">トップページを開く</a></p>
</body>
</html>
HTML;

上記の設定によって表示される 500 エラーページの例