我怎么能接受“不安全”呢?Windows Phone/Store应用中的HTTP响应头

本文关键字:不安全 应用 Store 响应 HTTP Phone Windows 能接受 | 更新日期: 2023-09-27 18:17:05

最近,使用HttpClient访问第三方REST API的Windows Phone 8.1 Silverlight应用程序中的一些代码停止工作。我得到了以下错误:

类型为'System '的第一次异常。mscorlib.ni.dll出现异常

附加信息:灾难性失败(Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))

在Windows Phone (Silverlight)和Store (RT)应用程序中尝试后,我在WPF中重写了相同的代码,最终得到了一个有用的错误消息:

服务器违反了协议。Section=ResponseHeader Detail=CR后面必须跟LF"

也有一篇很好的关于这个问题的深入的博客文章。

微软已经声明他们不会修复/允许这个,所以我要么被迫找到一个允许不安全头文件的第三方HTTP库,要么自己写。

我该如何解决这个问题?如果我从头开始编写自己的库,应该考虑哪些合适的类呢?有相关的样例代码吗?

(这个问题可能与这个问题太相似了,尽管在编写了一些测试代码之后,使用HttpClient的自定义处理程序的想法也不起作用,因为系统处理程序在响应时首先被调用。)

我怎么能接受“不安全”呢?Windows Phone/Store应用中的HTTP响应头

可以很容易地实现一个基本的HTTP客户端。忽略错误处理并处理Content-Length(稍后会详细介绍),这段代码应该可以达到目的。

var hostname = new HostName("www.w3.org");
var socket = new StreamSocket();
await socket.ConnectAsync(hostname, "80");
var request = "GET /Protocols/rfc2616/rfc2616-sec4.html HTTP/1.1'r'n" +
          "Host: www.w3.org'r'n" +
          "'r'n";
var writer = new DataWriter(socket.OutputStream);
writer.WriteString(request);
await writer.StoreAsync();
var reader = new DataReader(socket.InputStream);
reader.InputStreamOptions = InputStreamOptions.Partial;
string data = string.Empty;    
var cts = new CancellationTokenSource();
bool doneReading = false;
uint bytesToRead = 10240;
while (!doneReading)
{
  try
  {
    cts.CancelAfter(10 * 1000);
    await reader.LoadAsync(bytesToRead).AsTask(cts.Token);
    data += reader.ReadString(reader.UnconsumedBufferLength);
    totalBytesRead += bytesRead;
  }
  catch (TaskCanceledException)
  {
    doneReading = true;
  }
}
socket.Dispose();

肯定有一些问题需要解决:

  • 超时时间为10秒。但这取决于你使用的是哪种连接,也许这没问题?
  • 对于这个问题,等待超时是判断服务器是否完成发送数据的错误方法。正如Jon Skeet在使用StreamSocket正确接收数据挂起中提到的,客户端应该从报头中读取Content-Length并请求适当的字节数。当然,由于TCP是一个流,这也需要一些工作。

同样,这个解决方案主要适用于Windows Phone 8.1 Silverlight。虽然它也可以在Windows Phone 8.1/Windows Store(即WinRT)应用程序上运行,但在该平台上使用MessageWebSocket可能更容易。

由于这似乎是一个相当普遍的问题,我为此写了三篇系列文章;第2部分将讨论这种变通方法。同样值得注意的是,错误消息CR must be followed by LF可能不完全准确——它也可能意味着头中有一个无效字符(包括其中一个头名称中的空格)。