0

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

我有两个主要用例:

未发送标头

修复这里很简单,只需抛出 http 500 错误而不更改 url。

部分页面错误

在这种情况下,一些 html 和 http 标头已经发送到客户端。为了防止显示部分损坏的页面,我输出了导致完全重定向到错误页面 URL /error.html 的 javascript。这是为了避免显示正常页面的一部分和错误页面的一部分,并通过移动到专用的错误页面。

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

例如,如果在 index.php 中发送标头后出现错误,javascript 将输出将用户重定向到 /error.html。在那里,他们可以返回主页(应该没问题),或者回击。当他们回击时,他们可能会得到一个缓存页面,将他们重新重定向到 error.html。index.php > error.html(回击)缓存的 index.php > error.html

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

在下面的代码中,我尝试在 url 中添加 #error 哈希以仅在第一次重定向,并在后续访问损坏的部分页面时启动 60 秒的刷新尝试周期。不幸的是,当我设置 #error 哈希和重定向,然后回击时,它转到 index.php,而不是 index.php#error,因此发生了缓存的无限循环。

如何优雅地处理部分页面 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);
}
4

1 回答 1

0

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

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

于 2012-07-11T12:07:15.383 回答