防止在php中缓存500内部错误页面的问题


Problems with preventing caching of 500 internal error page in php

我在完全正确配置500个内部服务器错误页面的行为时遇到问题。

我有两个主要的用例:

未发送邮件头

这里的修复很简单,只需在不更改url的情况下抛出http500错误。

部分页面错误

在这种情况下,一些html&http标头已发送到客户端。为了防止部分损坏的页面显示,我输出了导致完全重定向到错误页面url/error.html的javascript。这是为了避免显示部分正常页面和部分错误页面,并明确表明即使错误消息最终显示的部分当前隐藏,所产生的html也不是最佳的,通过移动到专用错误页面。

不幸的是,当从专用错误页面点击"返回"时,原始错误页面会被缓存,并且会再次执行javascript重定向,即使在此期间错误已经修复。

例如,如果在index.php中发送标头后出现错误,javascript将输出将用户重定向到/error.html的内容。一旦出现错误,他们就可以返回主页(这应该很好),或者进行反击。当他们反击时,他们可能会得到一个缓存页面,该页面会将他们重定向到error.html。index.php>error.html(反击)缓存的index.php>error.html

避免这种情况的理想方法是什么?

在下面的代码中,我尝试在url中添加#error hash,以便仅在第一次重定向,并且在随后访问损坏的部分页面时开始60秒的刷新尝试周期。不幸的是,当我设置#error散列和重定向,然后进行反击时,它会返回到index.php,而不是index.php#错误,因此会发生缓存的无限循环。

如何优雅地处理部分页面500错误?

以下是我的php自定义错误处理程序中的代码,它导致了上面列出的行为:

function showErrorPage() {
    if (headers_sent()) {
    // This is complicated due to the infastructure tending to have already sent headers, ...
    // ...requiring a tuned javascript redirection in many instances.
        // Output the following as html.
        ?>
        <meta http-equiv="Cache-control" content="no-cache, no-store">
        <script type='text/javascript'>
        var currentHash = location.hash;
            // UNFORTUNATELY, HERE THE HASH NEVER SHOWS AS SET!
        if(!currentHash){ // If hash wasn't already set...
            location.hash = '#error';
            location.href = 'error.html'; // Redirect once.
        } else { // Otherwise, the hash was already set, they were redirected once but came back.
            // So just display this page for a time but refresh on a slow schedule.
            setTimeout(function(){
                location.reload(true); // Non-caching refresh.
            }, 60*1000); // Reload after 1 min delay
        }
        </script>
        <?php
    } else {
        // No headers sent, so set the right headers
        header("HTTP/1.1 500 Internal Server Error");
        header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
        header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
    }
    // Regardless, include the visible error output and throw exit with error.
    include(WEB_ROOT.'error.html');
    exit(1);
}

我找到了一个有用的解决方案,如下所示:

通过javascript,隐藏页面的所有部分,并用div中的错误消息替换它们。具体来说,我直接写出html,将其设置为隐藏样式,克隆它,删除body元素的所有子元素,并将错误div附加到body中,使其成为页面上唯一显示的通常会有很多站点元素的内容。