将HttpStatusCode用于应用程序错误是一种好习惯吗?

时间:2017-07-21 15:31:11

标签: c# httpclient

我们目前正在重建内部公司结构,正在与提供基于Http的界面的供应商(机器)交谈(如果我们付费的话)。我不被允许透露太多但是接口应该执行一个动作,并且这个动作可能由于各种原因而失败。我举一个例子

public HttpResponseMessage MoveItem(int item, string option)

现在这个原因可能成功或失败(例如)3个原因:

  • 成功:它有效,机器处于我想要的状态
  • 原因A:机器当前正在执行操作
  • 原因B:该项目不可用
  • 原因C:发生了另一个问题

现在供应商为此函数调用提供了以下返回值:

  • 成功:HttpStatusCode.OK
  • 原因A:HttpStatusCode.Conflict(409)
  • 原因B:HttpStatusCode.NoContent(204)
  • 原因C:HttpStatusCode.InternalServerError(500)

每一个都伴随着人类可读的信息。

现在我觉得这是一种奇怪的方法。根据我的理解(如果我错了,请纠正我!),似乎我们的供应商实际上错误地使用了Http状态代码来应对应用程序端错误。如果它适合我​​,如果调用失败,我实际上总会抛出异常并在该异常中提供详细信息。然而,我必须管理我直到今天才与HttpClient合作,所以我的知识目前有限(这会改变,不用担心)。

至于主要问题:我们的供应商的方法现在被认为是使用HttpClient的良好做法,并且是我们的供应商,或者我的感觉是正确的,这似乎有点像误用Http代码作为应用程序错误代码?

3 个答案:

答案 0 :(得分:2)

如果抛出异常,所有内容都会以500作为回调调用,并且唯一可以通过解析错误消息来区分错误发生的原因。这不是处理事情的好方法。通过发回不同的HTTP状态代码,调用应用程序可以基于来自服务的反馈采取行动。例如,如果你回到409,你可能会等待几秒钟然后再试一次,而如果你回到500则没有必要再次尝试。

我唯一可能的牛肉就是他们使用了204而不是404来表示没有找到某些东西,但那是假设"项目不可用"是"未找到/找到项目。"我可能误解了"不可用"的语义。在这种情况下,我的评论没有实际意义。

<强>更新

评论和其他帖子谈论&#34;劫持&#34;错误代码。如果这是一个真正的REST实现,我会同意。但事实并非如此。它更像是一个RPC调用。坦率地说,绝大多数所谓的&#34; REST&#34;我遇到的API只是JSON-over-HTTP(即基本上没有仪式的SOAP,用JSON代替XML)。

鉴于这一切,供应商的实施似乎对我来说很好。他们使用离散代码来指示操作的状态。只要这些代码在发布到发布时保持一致,它实际上是相同的。除此之外的任何争论都是学术性的,也是个人偏好的问题(模糊的警告,如果你进入项目后会出现问题&#34;尽管如此)。

答案 1 :(得分:2)

使用http代码指示错误类型很常见,但使用5xx以外的代码表示服务器内的问题不是。

一般来说,我对细节的倾向与你的一致,他们的错误代码是可疑的。

如果没有更多的内部细节,很难说肯定,并且关于http返回码的许多决定都是判断调用,因此我无法在此给出明确正确的答案。也就是说,我将您的描述与RFC 2616 中的描述进行了比较:

  • 原因A:机器当前正在执行操作

如果&#34;当前正在执行操作&#34;表示对同一资源的操作,这会产生某种冲突,然后409似乎对我来说是合适的。如果机器只是忙碌,那听起来就像503应该指示的那样。

  

10.5.4 503服务不可用

     

由于服务器临时过载或维护,服务器当前无法处理请求。这意味着这是一个暂时的条件,经过一段时间的延迟后会得到缓解。如果已知,则可以在Retry-After报头中指示延迟的长度。如果没有给出Retry-After,客户端应该像处理500响应一样处理响应。

     

10.4.10 409冲突

     

由于与资源的当前状态发生冲突,无法完成请求。此代码仅在预期用户可能能够解决冲突并重新提交请求的情况下才允许。响应主体应该包含足够的信息供用户识别冲突的来源。理想情况下,响应实体将包含足够的信息供用户或用户代理解决问题;但是,这可能是不可能的,也不是必需的。

     

最有可能发生冲突以响应PUT请求。例如,如果正在使用版本控制并且包含PUT的实体更改为与早期(第三方)请求所产生的资源冲突的资源,则服务器可能会使用409响应来指示它无法完成请求。在这种情况下,响应实体可能包含由响应Content-Type定义的格式的两个版本之间的差异列表。

  • 原因B:该项目不可用

如果服务器想要指示请求成功,但是没有找到任何内容,则204可能就足够了。如果不可用是临时情况,我认为5xx或3xx可能更合适,因为5xx可以指示临时(内部)问题,3xx表示客户端需要采取额外措施。

  

10.2.5 204无内容

     

服务器已完成请求但不需要返回实体主体,并且可能希望返回更新的元信息。响应可以包括实体标题形式的新的或更新的元信息,如果存在,应该与所请求的变体相关联。

     

如果客户端是用户代理,则它不应该从导致请求发送的文档视图中更改其文档视图。该响应主要是为了允许在不引起用户代理的活动文档视图的改变的情况下进行动作的输入,尽管任何新的或更新的元信息应当应当应用于当前在用户代理中的文档。积极的观点。

     

204响应绝不能包含消息体,因此总是在头字段之后的第一个空行终止。

     

10.3重定向3xx

     

此类状态代码表示用户代理需要采取进一步操作才能完成请求。当且仅当第二个请求中使用的方法是GET或HEAD时,所需的操作可以由用户代理执行而不与用户交互。客户端应该检测无限重定向循环,因为这样的循环会为每个重定向生成网络流量。

  • 原因C:发生了另一个问题 这看似合法。 500经常被用来作为一个全能的因为我们没有想到要解决的某些问题&#34;。

答案 2 :(得分:1)

我同意你的看法,这种做事方式有点愚蠢。 http状态代码是为http资源设计的,用于处理资源请求的状态,而不是用于传回由该资源控制的某个物理机器的状态。这是运输机制的地位。因此,他们将使用一些代码来表示他们不想要的东西。如果你的客户端应用程序按照他们使用它们的方式使用这些代码,那么我猜它是有效的,但它肯定是一种愚蠢的做事方式,并且它会在你进入项目的过程中引起问题。

我会像你一样,发回一个自定义异常并详细说明该异常中的问题。一些评论反对不得不深入研究异常以获取实际的错误数据。但这不是问题。客户端应用程序基本上会成功或失败,并且在失败时,其细节将失败。这并不像获取异常的细节就像获取状态代码一样低效。