web-dev-qa-db-ja.com

C#-接続:HttpWebRequest中にキープアライブヘッダーが送信されない

HttpWebRequestで次のヘッダーを送信するために送信しようとしています。

Connection: keep-alive

ただし、ヘッダーは送信されません。 Fiddler2は、Google Chromeでページをリクエストするたびにヘッダーが送信されることを示しています。しかし、私のアプリケーションは何らかの理由でこのヘッダーの送信を拒否しています。

KeepAliveプロパティをtrue(デフォルトではtrueに設定)に設定しましたが、ヘッダーはまだ送信されません。

複数のHttpWebRequestでこのヘッダーを送信しようとしていますが、基本的にはすべて次のようになります。

HttpWebRequest logIn6 = (HttpWebRequest)WebRequest.Create(new Uri(responseFromLogIn5));
logIn6.CookieContainer = cookies;
logIn6.KeepAlive = true;
logIn6.Referer = "https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/";
logIn6.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1";
logIn6.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
logIn6.Headers.Add("Accept-Encoding:gzip,deflate,sdch");
logIn6.Headers.Add("Accept-Language:en-US,en;q=0.8");
logIn6.Headers.Add("Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3");
logIn6.AllowAutoRedirect = false;

HttpWebResponse logIn6Response = (HttpWebResponse)logIn6.GetResponse();
string responseFromLogIn6 = logIn6Response.GetResponseHeader("Location");

cookies.Add(logIn6Response.Cookies);

logIn6Response.Close();

このヘッダーが送信されたことを確認するために私がしなければならないことを誰もが知っていますか?

ChromeからのFiddler2 Raw:

GET xxx HTTP/1.1
Host: accounts.google.com
Connection: keep-alive
Referer: https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: xxx

HTTP/1.1 302 Moved Temporarily
Set-Cookie: xxx
Set-Cookie: xxx
Location: xxx
Content-Type: text/html; charset=UTF-8
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
Date: Sat, 17 Sep 2011 22:27:09 GMT
Expires: Sat, 17 Sep 2011 22:27:09 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 2176
Server: GSE

私のアプリケーションから未加工のFiddler2:

GET xxx HTTP/1.1
Referer: https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Host: accounts.google.com

HTTP/1.1 302 Moved Temporarily
Location: xxx
Content-Type: text/html; charset=UTF-8
Date: Sun, 18 Sep 2011 00:05:40 GMT
Expires: Sun, 18 Sep 2011 00:05:40 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 573
Server: GSE

2番目のFiddler2の未加工情報を、最初のFiddler2の未加工情報のように取得しようとしています。

28

私は同じ問題を抱えていました:最初のリクエストを除いてConnection: Keep-Aliveヘッダーが送信されず、アクセスしたサーバーが見つからない場合、正しい応答を返しません。したがって、この問題に対する私の回避策は次のとおりです。

最初に、ProtocolVersionインスタンスのHttpWebRequestプロパティをHttpVersion.Version10に設定します。 httpコマンドがGET xxx HTTP/1.0になることを除いて、それは機能し、パブリックAPIのみを使用します。

2番目の方法では、リフレクションを使用して、HttpWebRequestインスタンスの内部プロパティServicePoint.HttpBehaviourを次のように変更します。

var req = (HttpWebRequest)WebRequest.Create(someUrl);

var sp = req.ServicePoint;
var prop = sp.GetType().GetProperty("HttpBehaviour", 
                        BindingFlags.Instance | BindingFlags.NonPublic);
prop.SetValue(sp, (byte)0, null);

req.GetResponse().Close();

お役に立てれば。

36
bigsan

私はこの問題に半日苦労しました!そして、親愛なる古いフィドラー(私の守護天使)は不注意にも問題の一部でした:

Fiddlerモニタリングを使用してHTTP POSTをテストするたびに-問題が表示されないFiddlerモニタリングをオフにしてHTTP POSTをテストするたびに-問題DIDが表示される

私のPOSTSはプロトコル1.1で送信され、キープアライブは最初の接続後に無視​​/冗長/理由が無視されました。つまり、最初のPOST(Fiddler!を介して)!)のヘッダーで確認できましたが、同じコードを使用しているにもかかわらず、後続のPOSTでは確認できませんでした。

ただし、リモートサーバーは、キープアライブが送信された場合にのみ応答します。これを証明することはできませんが、Fiddlerが接続を監視しているため、リモートサーバーが接続がまだアクティブであると考えたり信じたりして(最初のPOST後にキープアライブが送信されなかったにもかかわらず)正しく応答したと思われます。私が言ったように、2番目にFiddlerをオフにしたとき、キープアライブが存在しないため、リモートサーバーがタイムアウトになりました。

上記の1.0ソリューションを実装し、FiddlerをオンまたはオフにしてPOSTSが機能するようになりました。これが誰かがどこかに立ち往生するのを助けることを願っています...

8
Richard

あなたはそれを正しくやっています。コードにより、次のヘッダーが追加されます。

Connection: Keep-Alive

このヘッダーが表示されない場合は、FiddlerからのリクエストとRaw出力の送信に使用するコードを投稿してください。 HTTP 1.1接続は デフォルトでキープアライブ であるため、これを無視することもできます。

更新:.NETは最初の(!)リクエストに対してKeep-Aliveのみを明示的に設定するようです。基礎となるtcp接続がすでに再利用されているため、同じHost/urlへの以降のリクエストにはこのヘッダーはありません。

7
Dmitry

同じ問題があり、webclientを継承してGet Web Requestメソッドをオーバーライドすることでそれを解決することができたので、この答えを知っています。

以下のコードを参照してください。

    public class CookieAwareWebClient : WebClient
{
    public CookieContainer CookieContainer { get; set; }

    public CookieAwareWebClient()
        : this(new CookieContainer())
    { }

    public CookieAwareWebClient(CookieContainer c)
    {
        this.CookieContainer = c;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        var castRequest = request as HttpWebRequest;

        if (castRequest != null)
        {
            castRequest.KeepAlive = true; //<-- this what you want! The rest you don't need. 
            castRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
            castRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36";
            castRequest.Referer = "https://www.jobserve.com/gb/en/Candidate/Login.aspx?url=48BB4C724EA6A1F2CADF4243A0D73C13225717A29AE8DAD6913D";
            castRequest.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
            castRequest.Headers.Add("Accept-Language", "en-GB,en-US;q=0.8,en;q=0.6");
            castRequest.CookieContainer = this.CookieContainer;
        }

        return request;
    }
}

ご覧のとおり、キープアライブを有効にしているだけでなく、Cookieやその他のヘッダーも利用しています!

それがお役に立てば幸いです!

キラン

3
Prime By Design

HttpWebRequestソースコードをダウンロードした後、すべてのプロパティがHeaderCollectionのいくつかの既知のヘッダーをチェックすることに注意してください。そのコレクションでいくつかのリフレクションを行うことを取り除くために、それを動作させる

var webRequest = (HttpWebRequest) WebRequest.Create(url);
webRequest.Headers.GetType().InvokeMember("ChangeInternal",
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
    Type.DefaultBinder, webRequest.Headers, new object[] {name, value}
);
2
Pamir Erdem