web-dev-qa-db-fra.com

C # - Connexion: l'en-tête keep-alive n'est pas envoyé pendant HttpWebRequest

J'essaie d'envoyer pour envoyer l'en-tête suivant avec mon HttpWebRequest:

Connection: keep-alive

Cependant, l'en-tête n'est jamais envoyé. Fiddler2 montre que chaque fois que je demande la page dans Google Chrome, l'en-tête est envoyé. Cependant, ma candidature refuse d'envoyer cet en-tête pour une raison quelconque.

J'ai défini la propriété KeepAlive sur true (c'est true par défaut de toute façon), mais l'en-tête n'est toujours pas envoyé.

J'essaie d'envoyer cet en-tête avec plusieurs requêtes HttpWebRequests, mais elles ressemblent toutes à ceci:

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();

Quelqu'un sait-il ce que je dois faire pour m'assurer que cet en-tête est envoyé?

Fiddler2 Raw From Chrome:

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 Raw de mon application:

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

J'essaie d'obtenir la deuxième information brute de Fiddler2 pour qu'elle ressemble à la première information brute de Fiddler2.

28

J'ai eu le même problème: le Connection: Keep-Alive l'en-tête n'est pas envoyé sauf la première demande, et le serveur auquel j'ai accédé ne me donnera pas la bonne réponse s'il est manquant. Voici donc mes solutions de contournement à ce problème:

La première est de définir la propriété ProtocolVersion de l'instance HttpWebRequest sur HttpVersion.Version10. Sauf que la commande http deviendra GET xxx HTTP/1.0, il fonctionne et utilise uniquement l'API publique.

La deuxième façon utilise la réflexion pour modifier la propriété interne ServicePoint.HttpBehaviour de HttpWebRequest instance, comme ceci:

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();

J'espère que cela t'aides.

36
bigsan

J'ai lutté avec ce problème pendant une demi-journée! Et cher vieux Fiddler (mon ange gardien) faisait par inadvertance partie du problème:

Chaque fois que je testais mes POST HTTP en utilisant la surveillance Fiddler ON - le problème n'apparaissait PAS À chaque fois que je testais mes POST HTTP avec la surveillance Fiddler OFF - le problème DID apparaît

Mes messages ont été envoyés avec le protocole 1.1 et le Keep-Alive a été ignoré/redondant/pourquoi après la connexion initiale. c'est-à-dire que je pouvais le voir dans l'en-tête du premier POST (via Fiddler!), mais pas dans les POST suivants malgré l'utilisation du même code. Hé ho ...

Mais le serveur distant ne répondrait que si Keep-Alive était envoyé. Maintenant, je ne peux pas le prouver, mais je soupçonne que Fiddler surveillant la connexion a fait penser ou croire au serveur distant que la connexion était toujours active (malgré aucun Keep-Alives envoyé après mon premier POST) et a répondu correctement. Comme je l'ai dit, la seconde où j'ai éteint Fiddler, l'absence de Keep-Alives a provoqué un dépassement de délai du serveur distant.

J'ai implémenté la solution 1.0 décrite ci-dessus et mes POSTS fonctionnent maintenant, avec ou sans Fiddler activé ou désactivé. J'espère que cela aide quelqu'un d'autre coincé quelque part ...

8
Richard

Tu le fais bien. Le code doit entraîner l'ajout de l'en-tête suivant:

Connection: Keep-Alive

Publiez le code que vous utilisez pour envoyer la demande et la sortie brute de Fiddler si vous ne voyez pas cet en-tête. Vous pouvez également ignorer cela car la connexion HTTP 1.1 est garder en vie par défaut .

Mise à jour: il semble que .NET ne définit explicitement Keep-Alive que pour la première (!) Demande. Les autres demandes adressées au même hôte/URL n'auront probablement pas cet en-tête car la connexion TCP sous-jacente est déjà réutilisée.

7
Dmitry

Je connais la réponse car j'ai eu le même problème et j'ai réussi à le résoudre en héritant du client Web et en remplaçant sa méthode Get Web Request.

Voir le code ci-dessous:

    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;
    }
}

Comme vous pouvez le voir, j'active non seulement le maintien en vie, mais j'utilise également des cookies et d'autres en-têtes!

J'espère que ça aide!

Kiran

3
Prime By Design

Après avoir téléchargé HttpWebRequest le code source, vous avez remarqué que chaque propriété vérifie que HeaderCollection dans certains en-têtes connus. Pour se débarrasser de ça, faire des trucs de réflexion sur cette collection, ça marche

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