在C#中模拟HTTP的不正确的内容长度标头

时间:2009-08-25 16:15:25

标签: c# httpwebrequest content-length

我们正在为我们的应用程序在C#中构建一个全面的集成测试框架,它使用IIS7来托管我们的应用程序。

作为集成测试的一部分,我们希望测试传入的请求,这些请求将导致EndOfStreamExceptions(“无法读取超出流的末尾”),当客户端发送一个HTTP标头,表明体积大于实际传输时作为身体的一部分。我们想测试这个条件的错误恢复代码,因此我们需要模拟这些类型的请求。

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

4 个答案:

答案 0 :(得分:4)

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

但是:我不认为这个测试是个好主意。这是问题所在:

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

答案是服务器将假设这些字节是前一个请求的一部分并按原样对待它们,然后在启动后开始读取10个字节的“新”请求,这显然会导致标头格式错误。服务器不会那样,所以它会发送4xx错误,然后它将关闭连接。它关闭连接的原因是因为它现在无法知道发送给它的数据意味着什么并且无法恢复。此外,关闭连接将不会优雅,它将是突然的,另一端的HttpWebRequest提交第二个请求(如果排队等待,则为三分之一或四分之一)将抛出WebException,表示基础连接被关闭,让你猜测为什么。

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

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

答案 1 :(得分:0)

我不知道有任何这样的库,但在我看来,如果你正在编码那么它在接收方会非常简单。

只需检索整个WebRequest,根据需要截断尽可能多的内容,然后将其转发。您可能需要在此过程中创建WebRequest的新副本,而不是就地截断,但它应该仍然是直截了当的。

答案 2 :(得分:0)

您是否只能将客户端上的HttpWebRequest.ContentLength属性设置为比实际数据大小更小或更大的值?

答案 3 :(得分:0)

如果你想模拟任何违反HTTP协议的事情,那么你必须编写自己的代码才能完成。 HttpWebRequest不允许你做这样的事情。