HttpWebRequest in Compact Framework fails on second request

A

ajdavis

Hello, folks. A strange error that I finally tracked down with the
Ethereal packet sniffer:

Using .NET Compact Framework 1.0.3111 and programming C# in Visual
Studio .NET 7.1.3088, I create an HttpWebRequest. The first time, the
ProtocolVersion is 1.1 and the Host is correctly set in the HTTP
header. The second & all subsequent times, the same code produces a
request with ProtocolVersion 1.0, and the Host string is empty. This
sort of HTTP request fails for most hosts.

I'd love it if a few people w/ different versions of Windows CE, Visual
Studio, .NETCF, etc. tried this out. Make a new Smart Device
Application project, in the next dialog select "Pocket PC" or "Windows
CE" and "Windows Application". Then in the autogenerated Form1.cs, add
"using System.Net;" at the top, and insert the following in the Form1
constructor, below InitializeComponent():

TextBox output = new TextBox();
output.Multiline = true; output.ScrollBars = ScrollBars.Both;
output.Size = new Size(180, 220); this.Controls.Add(output);

for (int i = 0; i < 2; i++)
{
HttpWebResponse response = null;
HttpWebRequest request = null;
try
{
Uri url = new Uri("http://foobar.com/");
request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Timeout = 10 * 1000; // milliseconds
request.Method = "GET";
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version11;

response = (HttpWebResponse)request.GetResponse();

output.Text += string.Format("Received response of {0} bytes\r\n",
response.ContentLength);
}
catch (Exception e)
{
output.Text += "Exception: " + e.ToString() + "\r\n";
}
finally
{
if (response != null) response.Close();
}

output.Text += "Version: " + request.ProtocolVersion.ToString() +
"\r\n";
output.Text += "Host: " + request.Headers.Get("Host") + "\r\n";
output.Text += "======\r\n";
}

On my setup, I get the following output:

Received response of 2146 bytes
Version: 1.1
Host: foobar.com
======
Exception: System.Net.WebException:The remote server returned an
error: (503) Server Unavailable.
Version: 1.0
Host:
======

Notice how the Version is 1.0 and Host is empty in the second, failed,
request. Weird, huh? I filed a bug with MS, ID FDBK31733.

Jesse.
 
A

ajdavis

A friend helped me w/ the Ethereal packet-sniffer, & we've nailed down
the problem. My company uses the Squid transparent proxy, which
requires HTTP 1.1 requests but sends HTTP 1.0 responses. The .NETCF
pedantically refuses to send 1.1 requests to a host after it first gets
a 1.0 response from it. Here's what happens:

1) The .NET Compact Framework sends HTTP/1.0 requests, after the first
request, because Squid's response is HTTP/1.0, & the Framework decides
this server can only deal with HTTP/1.0. It correctly omits "Host"
from its 1.0 header. There's no way to force the Framework to include
the "Host" field, or to use an absolute Request-URI. There's also no
way to make Squid send HTTP/1.1 responses.

2) The most common way to use Squid is with DNAT (Destination Network
Address Translation), where the firewall rewrites the destination IP of
outgoing packets with the IP of the Squid proxy. (At my company, we do
this with an iptables command on the firewall.) So the destination IP
is lost, and Squid must have a Host entry, or an absolute Request-URI,
to determine the real destination.

3) The combination of these two properties means only the first
request to a given host can succeed. (I tested this, BTW: I can make
1 request to apple.com, 1 request to google.com, etc., in the lifetime
of 1 process.) Many HTTP implementations, like wget, include a Host
entry even in HTTP/1.0 requests, perhaps for this very situation. But
the Compact Framework doesn't.

The regular Framework succeeds these tests that the CF fails; I haven't
sniffed out the reason. I wish the CF allowed me to set the Host
field, or to force HTTP 1.1, or something more flexible than its
current implementation.

The workaround is to reimplement the required subset of HTTP 1.1 over
the provided Socket class, or to use SSL.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top