【问题标题】:Simulate Incorrect Content-Length Headers for HTTP in C#在 C# 中为 HTTP 模拟不正确的内容长度标头
【发布时间】:2009-08-25 16:15:24
【问题描述】:

我们正在使用 C# 为我们的应用程序构建一个全面的集成测试框架,该框架存在于 HTTP 之上,使用 IIS7 来托管我们的应用程序。

作为我们集成测试的一部分,我们希望测试传入请求,当客户端发送的 HTTP 标头指示正文大小大于实际传输的大小时,会导致 EndOfStreamExceptions(“无法读取超出流的末尾”)作为身体的一部分。我们想针对这种情况测试我们的错误恢复代码,因此我们需要模拟这些类型的请求。

我正在寻找一个基于 .NET Fx 的套接字库或自定义 HttpWebRequest 替代品,专门允许开发人员模拟此类条件以添加到我们的集成测试套件中。有谁知道任何这样的图书馆?可编写脚本的解决方案也可以。

【问题讨论】:

    标签: c# httpwebrequest content-length


    【解决方案1】:

    在调用 GetRequestStream(或 BeginGetRequestStream)之前设置 ContentLength 属性,然后向该流写入更少的字节。如果您在获得请求流后尝试设置 ContentLength,则会抛出异常。如果您不设置 ContentLength,HttpWebRequest 将缓冲标头,直到流关闭,以便它可以适当地设置 ContentLength(或者,您可以使用 SendChunked,但这对您不起作用)。如果您想最大程度地控制它,请手动创建一个或两个畸形请求,然后打开一个到服务器上端口 80 的套接字并将请求写入 TCP 流,然后读取响应并检查连接是否已关闭.

    但是:我认为这个测试不是一个好主意。问题来了:

    客户端向服务器发送请求。它声称内容将是 100 字节。然后它发送 90 个字节,然后停止发送,使连接保持打开状态。服务器读取 90 个字节,然后等待其余的,因为客户端说将发送 100 个字节。现在,客户端发送第二个请求。服务器将如何处理新请求的前 10 个字节?

    答案是服务器会假设这些字节是前一个请求的一部分并将它们视为这样,然后在开始后 10 个字节开始读取“新”请求,这显然会导致格式错误的标头。服务器不喜欢这样,所以它会发送一个 4xx 错误,然后它会关闭连接。它关闭连接的原因是它现在无法知道发送给它的数据意味着什么,也无法恢复。此外,连接的关闭不会是优雅的,它会是突然的,并且另一端的 HttpWebRequest 正在提交第二个请求(或者第三个或第四个,如果他们排队)将抛出一个 WebException 说底层连接已关闭,让您猜测原因。

    同样的行为是导致连接以 Expect 100-continue 标头关闭的原因,并且服务器返回 100-continue 后跟 4xx,例如当需要 Auth 时。即使它拒绝了请求,它仍然必须假设下一个字节是同一个请求的一部分,因为它已经承诺通过发送 100-continue 来接收这些字节。如果它不为该请求提供服务,或者如果客户端想要取消请求并提交一个新请求(可能带有身份验证凭据),那么它必须关闭连接并打开一个新请求。

    最后,使用 TCP 从网络流中测试 EndOfStreamException 对我来说根本没有任何意义。 TCP 不会标记流的“结束”,它只是在将数据写入套接字时继续发送数据。它没有“EOF”,也无法检测数据是否已全部传输,除非您知道预期有多少数据。除非连接关闭,否则 TCP 的流实际上并没有“结束”,在这种情况下,您将收到 WebException 或 SocketException,具体取决于您在堆栈中的操作位置。协议中的任何传输错误都在winsock中处理。如果不再发送数据,则连接的一端最终将向另一端发送保持连接,以确保连接实际上仍然处于打开状态,并且一台主机不会直接丢弃它。如果 keepalive 超时,连接将被关闭,并且您下次尝试从中读取时可能会收到 WebException。鉴于所有这些是如何工作的,我只是看不出你将如何从这个测试中获得任何价值。最好只发送格式错误的请求并确保相应地处理错误并将适当的 4xx 消息发送回客户端并正确关闭连接。

    【讨论】:

      【解决方案2】:

      我不知道有任何这样的库,但在我看来,如果您正在编码的话,接收端会非常简单。

      只需检索整个 WebRequest,尽可能多地或尽可能少地截断,然后继续转发。您可能需要在此过程中制作 WebRequest 的新副本,而不是就地截断,但它仍然应该是直截了当的。

      【讨论】:

      • 我们的集成测试模拟客户端。我们不能对接收方进行任何更改以方便测试。
      【解决方案3】:

      您不能将客户端上的HttpWebRequest.ContentLength 属性设置为小于或大于数据实际大小的值吗?

      【讨论】:

        【解决方案4】:

        如果您想模拟任何违反 HTTP 协议的事情,那么您将不得不编写自己的代码来执行此操作。 HttpWebRequest 不允许你做这样的事情。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-02
          • 1970-01-01
          • 2013-01-23
          • 2012-04-01
          • 1970-01-01
          • 2012-07-13
          • 2022-01-28
          • 1970-01-01
          相关资源
          最近更新 更多