您如何使用 Mura 和您的 Web 服务器处理 404 错误?

How do you handle 404 errors with Mura and your web server?

我已经搜索了答案,但未能找到确定的信息来源。我所追求的是 log/notify 对于 EVERY 404 错误的能力。我在网上找到的资料解决了一些 404错误,但不是全部。我做了一些测试,下面是测试的结果。您如何处理 Mura 网站的 404 错误?

我正在使用 IIS 和 Adob​​e ColdFusion 以及 Mura 6.2.6338。
我创建了自己的 onSite404 函数来从 Mura 捕获该事件。
我创建了自己的 ColdFusion 页面以在 IIS 触发它的 404 处理程序时进行捕获。

根据我的测试,似乎有一些内置的 Mura 功能可以处理来自网络根目录的 404。他们似乎不遵循标准的 404 执行模式。不确定我是否在任何地方看到过该记录?

我在一些测试中收到了几个超时错误。不知道为什么。可能是我尝试从我的自定义 IIS 404 页面调用正常 Mura 处理的方式。

基本上我想要的是让所有 IIS 404 错误调用我自己的自定义 ColdFusion 页面,我可以在其中 log/notify 错误,然后显示正常的 Mura 404 页面(不使用重定向因为这否定了用户的 404 状态代码)。

以下是我的测试结果:

仅定义了 Mura 404 页面:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       n/a    shows home page
/filedoesnotexist.htm                       No       n/a    shows home page
/filedoesnotexist.asp                       No       n/a    shows iis 404 error
/folderdoesnotexist/                        Yes      n/a    shows iis 404 error AND mura 404 page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      n/a    shows iis 404 error AND mura 404 page
/folderdoesnotexist/filedoesnotexist.htm    Yes      n/a    shows iis 404 error AND mura 404 page
/folderdoesnotexist/filedoesnotexist.asp    No       n/a    shows iis 404 error

定义了 Mura 404 页面并且 IIS 404 指向同一个 Mura 404 页面/index.cfm/404/:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No     Unknown  shows home page
/filedoesnotexist.htm                       No     Unknown  shows home page
/filedoesnotexist.asp                       No     Unknown  shows mura 404 page
/folderdoesnotexist/                        Yes    Unknown  shows mura 404 page
/folderdoesnotexist/filedoesnotexist.cfm    Yes    Unknown  shows mura 404 page
/folderdoesnotexist/filedoesnotexist.htm    Yes    Unknown  shows mura 404 page
/folderdoesnotexist/filedoesnotexist.asp    No     Unknown  shows mura 404 page

定义了 Mura 404 页面并且 IIS 404 指向它自己的 404 页面/iis404.cfm:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       No     shows home page
/filedoesnotexist.htm                       No       No     shows home page
/filedoesnotexist.asp                       No       Yes    shows custom iis 404 page
/folderdoesnotexist/                        Yes      Yes    shows custom iis 404 page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      Yes    shows custom iis 404 page
/folderdoesnotexist/filedoesnotexist.htm    Yes      Yes    shows custom iis 404 page
/folderdoesnotexist/filedoesnotexist.asp    No       Yes    shows custom iis 404 page

定义了 Mura 404 页面并且 IIS 404 指向它自己的 404 页面 /iis404.cfm 在通过 application.contentServer.handleRootRequest() 调用 Mura 处理的 Web 根目录中:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       No     shows home page
/filedoesnotexist.htm                       No       No     500 Internal server error – coldfusion.runtime.RequestTimedOutException on query
/filedoesnotexist.asp                       No       Yes    shows home page
/folderdoesnotexist/                        Yes      Yes    shows home page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      Yes    shows home page
/folderdoesnotexist/filedoesnotexist.htm    Yes      Yes    shows CF sitewide error page - coldfusion.runtime.RequestTimedOutException on query
/folderdoesnotexist/filedoesnotexist.asp    No       Yes    shows home page

定义了 Mura 404 页面并且 IIS 404 指向它自己的 404 页面 /siteid/iis404.cfm 在通过 application.contentServer.parseURLLocal() 调用 Mura 处理的站点 id root:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       No     shows home page
/filedoesnotexist.htm                       No       No     500 Internal server error – coldfusion.runtime.RequestTimedOutException on query
/filedoesnotexist.asp                       No       Yes    shows home page
/folderdoesnotexist/                        Yes      Yes    shows home page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      Yes    shows home page
/folderdoesnotexist/filedoesnotexist.htm    Yes      Yes    shows CF sitewide error page - coldfusion.runtime.RequestTimedOutException on query
/folderdoesnotexist/filedoesnotexist.asp    No       Yes    shows home page

Mura 似乎正在处理任何 ColdFusion 404 错误除了网络根目录,我可以在 onSite404 方法中进行处理。但是我不知道如何获取其他 404 错误来进行我的处理 AND 调用 Mura 404 页面以显示给用户。

只是记录更多发现。我在几篇在线博客文章中发现,对于 IIS,您应该在配置的 httpErrors 部分下将 existingResponse 设置为 PassThrough,这将解决一些 404 问题。好吧,这是我进行更改后的测试结果:

定义了 Mura 404 页面并且 IIS 404 指向它自己的 404 页面 /iis404.cfm 并且 IIS httpErrors 设置为 PassThrough for existingResponse:

Requested URL                           onSite404  IIS 404  Displayed
                                         called     called
/filedoesnotexist.cfm                       No       No     shows home page
/filedoesnotexist.htm                       No       No     shows CF sitewide error page - coldfusion.runtime.RequestTimedOutException on query
/filedoesnotexist.asp                       No       No     shows blank 404 page
/folderdoesnotexist/                        Yes      No     shows mura 404 page
/folderdoesnotexist/filedoesnotexist.cfm    Yes      No     shows mura 404 page
/folderdoesnotexist/filedoesnotexist.htm    Yes      No     shows mura 404 page
/folderdoesnotexist/filedoesnotexist.asp    No       No     shows blank 404 page

因此,使用此配置,IIS 404 似乎从未实际调用我的 ColdFusion 模板。更糟糕的是,对于某些请求,它只会发送一个空白的 404 响应。我想按设计工作,因为 PassThrough 告诉它只传递响应。

记录@Grant 回答后的另一个结果。我已经尝试过 Mura 的 standard404Handler 方法,但不想覆盖它的所有功能,因为老实说,我不确定它在做什么,也不想破坏一些标准的 Mura 功能。另外,我看到正是从这个方法中调用了 onSite404 方法。所以我假设覆盖 standard404Handler 方法的测试结果与使用“onSite404”方法时没有什么不同。我的测试结果支持这一点。

定义了 Mura 404 页面并且 IIS 404 指向它自己的 404 页面 /iis404.cfm 并覆盖 Mura standard404Handler:

Requested URL                           onSite404  IIS 404  standard404Handler  Displayed
                                         called     called    called
/filedoesnotexist.cfm                       No        No        No              shows home page
/filedoesnotexist.htm                       No        No        No              shows home page
/filedoesnotexist.asp                       No        Yes       No              shows custom iis 404 page  
/folderdoesnotexist/                        No        No        Yes             shows mura 404 page
/folderdoesnotexist/filedoesnotexist.cfm    No        No        Yes             shows mura 404 page
/folderdoesnotexist/filedoesnotexist.htm    No        No        Yes             shows mura 404 page  
/folderdoesnotexist/filedoesnotexist.asp    No        Yes       No              shows custom iis 404 page  

现在很明显,我需要使用 Mura onSite404 方法和 IIS 配置中的某种自定义 404 处理程序。因此,如果我能找到一种方法来显示 Mura 404 页面,同时保留 404 状态代码,那么在我的自定义 404 处理程序运行后,这将解决我的问题。

我认为也许挂接到 standard404Handler() 事件是最简单的解决方案。

有几种方法,但最简单的方法是在 Mura 中创建一个名为“404”的页面(您已经完成),然后将其放入站点的 /includes/eventHandler.cfc:

function standard404Handler( $,event ) {
    /* writeDump("hi, I'm a Mura 404!"); abort; */
    /* --- do custom stuff like logging, etc. --- */
    location( $.createHREF( filename="404") );
}

(如果将上面的内容放在老式 cfc 中,请确保将其包裹在 cfscript 标签中)

这应该可以解决问题。请注意,通过调用此事件,您将覆盖 Mura 的标准 404 处理行为(毕竟,这是此事件背后的意图)。因此,您负责 all Mura 404 处理...因此在函数末尾重定向到 404 页面。您可以在此处查看 Mura 页面请求流的所有 "handler" 事件:

http://docs.getmura.com/v6/back-end/events/life-cycle-of-a-front-end-request/

感谢您的回复。我尝试了更多,并认为我可能找到了解决方案。它需要进一步测试,但到目前为止一切顺利。请记住 - 我在这里之后的目的是记录 and/or 通知任何 404 错误,return Mura 404 页面内容和 return 适当的 404 状态代码。

事实证明,Mura 已经有一个非常可靠的解决方案来处理像 /some_non_existent_folder/some_non_existent_file.cfm 这样的 ColdFusion 404 错误。如果您创建了一个名为“404”的页面,那么 Mura 将显示该页面和 return 正确的 404 状态代码。

问题是 Mura 不会也不应该处理非 cfm 页面的 404 错误,例如 /some_non_existent_folder/some_non_existent_file.jpg。相反,这些由您的网络服务器(在我的例子中是 IIS)处理。所以我们需要定义一个自定义页面来处理这些 IIS 404 错误。这样我们就可以 log/notify 并最终向用户显示 404 页面内容和 return 正确的 404 状态代码。

首先让我重申,我仍然没有针对网络根目录中的文件(如 /some_non_existent_file.cfm/some_non_existent_file.jpg)发生的 404 错误的解决方案。 Mura 本身不显示定义的 404 页面。而是显示主页。我认为 IIS URL 重写规则会在任何错误处理发生之前捕捉到这些。但我对此没意见。

对于所有其他 404 错误,这就是我所做的。我在测试中发现,当我定义了 onSite404 方法并定义了自定义 IIS 404 处理程序时,两者都会因 ColdFusion 丢失的文件而被触发,而只有 IIS 处理程序用于非 cfm 文件。我不需要处理这些两次,所以我删除了我定义的 onSite404 方法。这只留下指向我创建的 ColdFusion 页面的自定义 IIS 404 处理程序(在 Mura 之外)。

我的最后一步是找到一种方法来调用我们创建的 Mura 404 页面,但仍然是 return 正确的 404 状态代码。这就是内置 Mura 处理的作用所在。正如我所提到的,Mura 已经可以正确处理丢失的 .cfm 文件。所以我仔细研究了 Mura 代码,看看他们是如何调用 404 页面的,看看我是否可以复制它。这是我找到的代码,似乎对我有用。我将它放在 IIS 404 处理程序调用的自定义 ColdFusion 页面的末尾。

<cfinvoke component="/requirements/mura/content/contentServer" method="render404" />

contentServer.cfcrender404 方法似乎可以完美地显示 Mura 404 页面内容,并且仍然 return 正确的 404 状态代码。

如果有人知道以这种方式调用此方法有任何问题,请告诉我。

我想指出的一件事是,默认情况下,Mura 不会在丢失 .cfm 文件时抛出 404。这是预期行为,以便您可以将现有应用程序与 Mura 集成。如果你想覆盖这个行为,你可以使用下面的方法:

<cfscript>
  // drop this into your SITE or THEME eventHandler.cfc to trigger a 404 on missing .cfm files
  public any function onSiteRequestStart($) {
    request.uri = GetPageContext().GetRequest().GetRequestURI();
    request.template = Right(request.uri, 1) != '/' ? ListLast(request.uri, '/') : '';
    if ( Len(request.template) && !FileExists(ExpandPath(request.template)) ) {
      request.currentfilenameadjusted = request.template;
    }
  }
</cfscript>