【问题标题】:How should internal web api errors be handled?应该如何处理内部 web api 错误?
【发布时间】:2013-01-02 12:40:28
【问题描述】:

在我们的应用程序中,我们有一组相当简单的日志记录钩子(MVC 和 API 控制器上的 IExceptionFilters 以及 Application_Error() 中的一个额外的包罗万象),但是有一整类错误不会触发任何错误.如果从 WebAPI 本身或内部使用的东西(例如由依赖解析器创建的类的类型初始化程序)抛出异常,我得到的只是发送到客户端的 500 响应。

我发现捕获错误详细信息的唯一方法是使用 HttpConfiguration.IncludeErrorDetailPolicy 配置应用程序以发出错误详细信息 - 但是,将错误详细信息广播到全世界是一种明显的不良做法,所以我会更喜欢完全关闭它,或者将其设置为有条件的(例如,仅限本地。)..但这意味着远程进入运行应用程序的服务器并使用可以检查响应的工具在本地调用 API(比如IE 或谷歌浏览器),以便弄清楚发生了什么。

我在这里看到了另一个类似的问题 (here),但是提出的解决方案(使用 DelegatingHandler 来检查响应)不能满足我们的需求,我们认为。真的没有我可以挂钩的事件、我可以使用的扩展点或类似的东西来捕获发生的实际异常吗?

(顺便说一句,我想我可以将我的 IncludeErrorDetailPolicy 更改为 Always 并使用其他线程中提供的解决方案来捕获 MessageHandler 中的错误详细信息,记录它们,并从发送给客户端的响应中手动清除它们,但那将是一个令人讨厌的黑客攻击。)

想法? :/

【问题讨论】:

  • 为什么 MessageHandler 方法不适合你?
  • 我可能会误解它,但从我阅读它的方式来看,获取我可以记录的异常对象的唯一方法是遵循我的问题末尾提到的黑客 - 到启用在所有响应中包含错误详细信息,然后在错误中解析该错误详细信息以尝试重建最初引发的异常,然后在将响应发送到客户端之前手动清除响应中的这些详细信息。 ..虽然这应该可行,但它听起来很粗糙、脆弱,并且容易丢失诊断信息和/或无意中将这些信息泄露给客户。
  • 您想保留诊断信息避免将信息泄露给客户端吗?你想发回什么样的回复?为什么默认设置对您不起作用?出于调试目的,您将在本地计算机上获得完整的诊断信息,并且不会向远程客户端泄露任何信息。
  • 嗯,是的 - 我的目的是在服务器上捕获尽可能多的信息,并将最小的响应发送到客户端。问题是,对于大多数错误,我们使用框架中的内置机制来捕获日志记录的错误详细信息(MVC 和 HTTP IExceptionFilters 以及 Application_Error 事件),这一切都很好,但似乎有一个类别Web api 内部和周围的错误,其中不存在这种机制 - 或者,至少,我找不到。

标签: logging error-handling asp.net-web-api


【解决方案1】:

好的,我明白你想要做什么。感谢您的澄清。 WebAPI 有一个模型,错误响应不一定是由异常引起的。例如,任何人都可以返回带有 400 的 HttpResponseMessage 而不会实际抛出异常。而且在许多情况下,内置框架错误的工作方式相同,不会引发异常。

现在,我认为您的建议对我来说听起来不错。您可以将 ErrorDetailPolicy 设置为 Always,并实现一个消息处理程序来记录错误并使用仅包含消息的不同 HttpError。下面是它的样子:

public class ErrorHandlingMessageHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
        HttpError error;
        if (response.TryGetContentValue(out error))
        {
            LogError(error)
            // Use an HttpError that doesn't leak internal information
            (response.Content as ObjectContent).Value = new HttpError(error.Message);
        }

        return response;
    }
}

请注意,我们并未清除现有错误。我们正在创建一个新的以降低信息泄露的风险。消息应该始终可以安全地发回。这不包括发回模型状态,但如果您需要,您可以随时将其复制到新错误中。

对此的一种思考方式是,您可以记录您将发送到本地客户端的响应,然后仍然向远程客户端发送不包含错误详细信息的安全消息。

【讨论】:

    【解决方案2】:

    我们向 Microsoft 合作伙伴网络提出了支持请求,他们回复了我认为更好的答案。

    想法是将平台的默认 IHttpControllerActivator 实现替换为将默认控制器创建行为与任何其他所需行为封装在一起的实现。

    在我们的例子中,这意味着使用 try/catch/throw 结构和对我们的日志服务的调用来包装 DefaultHttpControllerActivator 的 Create 方法。这可能无法提供 100% 的覆盖率,但我们遗漏的大多数异常都与控制器的创建有关,因此它应该会有很大帮助。

    我真的很想能够在 HttpControllerDispatcher 中挂钩 HandleException 方法,但它既是私有的又是静态的,所以嗯。

    【讨论】:

    • +1,只是一个注释:也替换IHttpControllerSelectorIHttpActionSelectorIHttActionInvoker以完全控制这些内部错误。
    猜你喜欢
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 2018-05-08
    • 2017-11-07
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多