宜昌市文章资讯

Nginx错误拦截转发 error_page的问题解决

2026-03-30 15:35:02 浏览次数:2
详细信息

error_page的配置和常见问题解决方案。

一、error_page基础配置

1. 基本语法

error_page code [code...] [=response] uri;

2. 常见配置示例

http {
    # 全局错误页面
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;

    server {
        listen 80;

        # 指定错误页面的位置
        location = /404.html {
            root /usr/share/nginx/html;
            internal;
        }

        location = /50x.html {
            root /usr/share/nginx/html;
            internal;
        }
    }
}

二、常见问题及解决方案

问题1:error_page不生效

可能原因及解决方案:

# 错误:使用了proxy_intercept_errors off(默认值)
location / {
    proxy_pass http://backend;
    proxy_intercept_errors off;  # ← 这会导致错误不被nginx拦截
}

# 正确:开启错误拦截
location / {
    proxy_pass http://backend;
    proxy_intercept_errors on;  # ← 关键设置
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
}

问题2:重定向死循环

# 错误:可能导致重定向循环
error_page 404 /404.html;  # 如果404.html本身不存在,会无限循环

# 解决方案1:确保错误页面存在
location = /404.html {
    root /var/www/html;
    internal;  # 防止直接访问
}

# 解决方案2:使用绝对路径
error_page 404 http://example.com/custom-404.html;

# 解决方案3:设置状态码
error_page 404 =200 /404.html;  # 返回200状态码

问题3:代理后端错误不显示自定义页面

server {
    listen 80;

    location / {
        proxy_pass http://backend;
        proxy_intercept_errors on;  # 必须开启

        # 处理后端返回的错误
        error_page 404 = @fallback;
        error_page 500 502 503 504 = @maintenance;
    }

    location @fallback {
        # 返回静态错误页面
        root /var/www/error_pages;
        try_files /404.html =404;
    }

    location @maintenance {
        root /var/www/error_pages;
        try_files /50x.html =500;
    }
}

问题4:动态错误处理

# 使用命名location处理错误
error_page 404 @error_handler;

location @error_handler {
    # 记录到日志
    access_log /var/log/nginx/errors.log;

    # 重写到PHP处理程序
    rewrite ^ /error.php?code=$status last;
}

location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php-fpm.sock;
    include fastcgi_params;
    fastcgi_param REQUEST_URI $request_uri;
    fastcgi_param ERROR_CODE $status;
}

问题5:不同状态码的统一处理

# 捕获多个状态码
error_page 401 403 404 /error.html;

location = /error.html {
    internal;
    root /usr/share/nginx/html;

    # 根据状态码显示不同内容
    if ($status = 401) {
        set $error_msg "需要登录";
    }
    if ($status = 403) {
        set $error_msg "禁止访问";
    }
    if ($status = 404) {
        set $error_msg "页面不存在";
    }

    # 可以在HTML中通过变量显示:$error_msg
}

三、高级配置示例

1. 根据请求类型返回不同格式

map $http_accept $error_format {
    default "html";
    "~application/json" "json";
    "~application/xml" "xml";
}

server {
    error_page 404 = @error;

    location @error {
        # 根据Accept头返回不同格式
        if ($error_format = "json") {
            return 404 '{"error": "Not Found", "code": 404}';
        }
        if ($error_format = "xml") {
            return 404 '<?xml version="1.0"?><error><message>Not Found</message><code>404</code></error>';
        }

        # 默认返回HTML
        root /var/www/errors;
        try_files /404.html =404;
    }
}

2. 维护模式配置

# maintenance.conf
error_page 502 503 504 /maintenance.html;

location = /maintenance.html {
    root /usr/share/nginx/html;
    internal;
}

# 在需要维护时使用
if (-f /var/www/maintenance.flag) {
    return 503;
}

3. 完整示例配置

http {
    # 定义错误页面根目录
    error_page 404 /error/404.html;
    error_page 500 502 503 504 /error/50x.html;
    error_page 403 /error/403.html;

    server {
        listen 80;
        server_name example.com;

        # 错误页面目录
        location ^~ /error/ {
            internal;
            root /var/www/html;
        }

        # 主要应用
        location / {
            proxy_pass http://backend;
            proxy_intercept_errors on;

            # 错误处理
            error_page 404 = @not_found;
            error_page 500 502 503 504 = @server_error;
            error_page 403 = @forbidden;
        }

        # 自定义错误处理location
        location @not_found {
            # 可以记录日志、统计等
            access_log /var/log/nginx/404.log;

            # 返回自定义页面
            return 302 /error/404.html;
        }

        location @server_error {
            # 发送警报邮件(通过脚本)
            # ...

            # 返回错误页面
            root /var/www/html/error;
            try_files /50x.html =500;
        }

        location @forbidden {
            # 重定向到登录页面
            return 302 /login?return_url=$request_uri;
        }
    }
}

四、调试技巧

1. 检查配置

# 检查语法
nginx -t

# 详细测试配置
nginx -T

# 重新加载配置
nginx -s reload

2. 查看日志

# 查看错误日志
tail -f /var/log/nginx/error.log

# 查看访问日志中的错误
grep " 50[0-9] " /var/log/nginx/access.log

3. 测试错误响应

# 测试404
curl -I http://localhost/nonexistent

# 测试500错误
curl -I http://localhost/trigger-error

五、最佳实践建议

始终设置proxy_intercept_errors on 当使用反向代理时 使用internal指令 防止错误页面被直接访问 确保错误页面文件存在 并且有正确的权限 考虑错误页面的缓存策略 记录错误到日志 便于分析 根据业务需求定制错误页面 提供更好的用户体验

需要根据你的具体业务场景选择合适的配置方式。

相关推荐