NGINXで発生した404エラー時にアプリ側のエラー画面を表示させる

投稿日: 2022/10/28
更新日: 2022/10/28
シェア:

URL copied!


概要

NGINX 側で静的ファイルを見せていた場合、静的ファイルが見当たらなかった場合 NGINX 側で404エラーを出すことになる。これをリバースプロキシしているアプリ側が作成する404ページに置き換えたい。

結論だけで良い方はこちらへ

試してみる

気になったときは Docker を使って検証。

通常の404ページを表示してみる

docker コンテナ起動

docker run --name test_nginx -d -p 8999:80 nginx

http://localhost:8999 でデフォルトの画面が見えることを確認。

docker の中に入る

docker exec -it test_nginx

編集したいので vim を入れる

apt update
apt install vim

デフォルトの設定を確認

vim /etc/nginx/conf.d/default.conf  
# default.conf
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    ... 

404ページを表示できるように設定を変更

(ついでにスペースもこんなにいらないので消した)

vim /etc/nginx/conf.d/default.conf

    ...
    #error_page  404              /404.html;
    error_page 404 /404.html;
    ...

404.html ファイルを作成

※ 検証のためだけなのでHTMLの書き方も無視します。

echo "test 404 page!" > /usr/share/nginx/html/404.html

設定を読み込ませるためにリロード

リロードする前に http://localhost:8998/aaaa にアクセス。
するとデフォルトの以下のような画面が出る。

ここでリロードして

service nginx reload

再度同じように実行してみると、test 404 page! とかかれた独自のエラーページが見えることがわかる。

アプリのURLを指定する

簡単なアプリを作る(Flask)

どこかローカル環境で python の仮想環境を作る。

python3 -m venv venv
source venv/bin/activate

flask のチュートリアルをもじって404の内容を示すページを作成。

# error.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

@app.route("/error/404")
def error_404():
    return "<p>404 error from flask</p>"

実行する

flask --app error run -p 5555

http://localhost:5555/http://localhost:5555/error/404にそれぞれ表示したい文字が出ることが確認できる。

NGINX と組み合わせる

vim /etc/nginx/conf.d/default.conf

    ...
    #error_page 404 /404.html;
    error_page  404 http://$host:5555/error/404;
    ...

NGINX をリロード

service nginx reload

すると、http://localhost:8998/aaaa にアクセスすると、http://localhost:5555/error/404 にリダイレクトされていることがわかります。

結論

error_page の構文でアプリ側のURLを指定するとリダイレクトされる。他のエラーも同様に可能です。

error_page 404 <URL>

参考

error_page - NGINX
Handling Errors - NGINX

終わりに

共通化することで、アプリ側で生成する404ページはリニューアルしたのに、 NGINX で表示している静的なファイルとして作成した404ページの更新忘れたということは無くせるはずです。