HttpWebRequest没有发送头部信息。

5
我正在尝试使用HttpWebRequest类模拟POST Web请求:
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(<my url>));
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = data.Length;
        using (Stream stream = request.GetRequestStream())
        {
            stream.Write(data, 0, data.Length);
        }
        request.UserAgent = @"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)";

我需要为请求设置cookie。我尝试了两种方法:

request.Headers.Add(HttpRequestHeader.Cookie, GetGlobalCookies(<cookies url>));

 [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, StringBuilder pchCookieData, ref uint pcchCookieData, int dwFlags, IntPtr lpReserved);
    const int INTERNET_COOKIE_HTTPONLY = 0x00002000;

    public static string GetGlobalCookies(string uri)
    {
        uint datasize = 1024;
        StringBuilder cookieData = new StringBuilder((int)datasize);
        if (InternetGetCookieEx(uri, null, cookieData, ref datasize, INTERNET_COOKIE_HTTPONLY, IntPtr.Zero)
            && cookieData.Length > 0) {
            return cookieData.ToString(); //.Replace(';', ',');
        }
        else
        {
            return null;
        }
    }

并且

request.CookieContainer = new CookieContainer();
request.CookieContainer.SetCookies(new Uri(<my url>), GetGlobalCookies(<cookies-url>).Replace(';', ','));

GetGlobalCookies()返回了我需要的正确的cookie字符串。但是在运行request.GetResponse()后,我的请求在Fiddler中看起来像这样:

POST <my url> HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: <my host>
Content-Length: 3
Expect: 100-continue
Connection: Keep-Alive

i=1

如果我将方法更改为GET,则cookie会被正确发送,但仍然没有User-Agent。
GET <my url> HTTP/1.1
Cookie: ASP.NET_SessionId=uajwt1ybpde4hudwwizuq2ld
Host: <my host>
Connection: Keep-Alive

为什么HttpWebRequest没有发送Cookie和User-Agent头?
1个回答

11

好的,我自己想通了。当你调用GetRequestStream()时,HttpWebRequest会构造请求体,因此在调用GetRequestStream()之前必须设置所有必需的标头,否则它们将不会被发送。


1
这一点绝对应该在微软文档中用粗体字写出来。今天我度过了美好的一天,弄清楚了这个事实(非常重要的Referer头丢失了,我不知道为什么)。https://learn.microsoft.com/en-us/dotnet/framework/network-programming/how-to-send-data-using-the-webrequest-class列出了需要按正确顺序执行的步骤,但他们必须在文档中某处写下这个可怕的事实:<strong>在设置所有标头之前不要调用GetRequestStream()</strong>。 - Remigijus Pankevičius
他们专门为常见的头部(如Content-Type)制作了setter。您无法手动设置Content-Type标头;它不会让您这样做。通过这样做,他们在说“我们将为您处理Content-Type标头”。然后他们没有设置Content-Type标头。微软怎么回事?要么让开发人员拥有控制权和责任,要么为他们完成。这种半途而废的解决方案不会取悦任何人。有趣的是,他们本可以修复这个问题。这只会对严重疏忽的代码造成破坏性影响,但他们从未这样做过,也永远不会这样做。 - LinuxDisciple

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接