291 votes

Comment définir un cookie sur HttpRequestMessage de HttpClient

Je suis en train d'essayer d'utiliser HttpClient de l'API web pour faire un post vers un point de terminaison qui nécessite une connexion sous forme d'un cookie HTTP qui identifie un compte (c'est quelque chose qui est seulement #ifdefé dans la version finale).

Comment ajouter un cookie à HttpRequestMessage ?

431voto

Darin Dimitrov Points 528142

Voici comment vous pourriez définir une valeur de cookie personnalisée pour la requête :

var baseAddress = new Uri("http://example.com");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var content = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair("foo", "bar"),
        new KeyValuePair("baz", "bazinga"),
    });
    cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
    var result = await client.PostAsync("/test", content);
    result.EnsureSuccessStatusCode();
}

2 votes

Le gestionnaire peut être supprimé de l'instruction d'utilisation, il sera libéré lorsque le client http sera libéré.

21 votes

Kimi a raison, mais vous ne devriez pas non plus envelopper votre HttpClient dans un using. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong

13 votes

ATTENTION : si vous utilisez une seule instance de HttpClient pour effectuer plusieurs requêtes, les cookies utilisant CookieContainer sont mis en cache. Il est dangereux pour un utilisateur de récupérer le cookie d'un autre utilisateur.

399voto

Greg Beech Points 55270

La réponse acceptée est la manière correcte de le faire dans la plupart des cas. Cependant, il y a des situations où vous voulez définir manuellement l'en-tête du cookie. Normalement, si vous définissez un en-tête "Cookie", il est ignoré, mais c'est parce que HttpClientHandler utilise par défaut sa propriété CookieContainer pour les cookies. Si vous le désactivez en définissant UseCookies sur false, vous pouvez définir manuellement les en-têtes de cookie et ils apparaîtront dans la requête, par exemple :

var baseAddress = new Uri("http://example.com");
using (var handler = new HttpClientHandler { UseCookies = false })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var message = new HttpRequestMessage(HttpMethod.Get, "/test");
    message.Headers.Add("Cookie", "cookie1=value1; cookie2=value2");
    var result = await client.SendAsync(message);
    result.EnsureSuccessStatusCode();
}

58 votes

J'ai cherché pendant plusieurs jours une erreur dans laquelle les requêtes envoyées avec SendAsync ne envoyaient pas l'en-tête de cookie; cela m'a aidé à réaliser que, sauf si vous définissez UseCookies = false dans le gestionnaire, il n'utilisera pas seulement le CookieContainer, mais aussi ignorera silencieusement tout Cookie stocké dans les en-têtes de requête! Merci beaucoup!

16 votes

Cette réponse est extrêmement utile pour quiconque essaie d'utiliser HttpClient comme proxy!

3 votes

Essayer ça maintenant... Si ça marche... tu mérites un bon vieux câlin canadien.

7voto

Waqar UlHaq Points 301

Pour moi, la solution simple fonctionne pour définir les cookies dans l'objet HttpRequestMessage.

protected async Task SendRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken = default(CancellationToken))
{
    requestMessage.Headers.Add("Cookie", $"=;=");

    return await _httpClient.SendAsync(requestMessage, cancellationToken).ConfigureAwait(false);
}

0 votes

Notez que la réponse acceptée fait beaucoup plus et gère beaucoup plus de conditions limites que cela. Il peut être utilisé pour faire des choses comme les cookies http uniquement ou à portée limitée, les cookies à valeurs multiples, etc. La deuxième réponse la mieux notée propose la même méthode que celle-ci mais avec beaucoup plus de contexte et d'explications

0 votes

@GeorgeMauer peut-être que tu as raison. Les deux créent un httpClient à partir de "HttpClient(handler)". Dans mon cas, je crée _httpClient à partir de httpClientPool.GetOrCreateHttpClient()

2 votes

Mais vous ne montrez pas réellement cela dans votre réponse ni n'expliquez la différence ou les avantages (ce n'est pas non plus réellement la question, mais je ne m'inquiète pas pour cela). Je n'essaie pas d'être impoli, il est simplement important d'être clair pour qui cette réponse serait utile et qui ne serait pas mieux aidé par les autres.

6voto

Amir No-Family Points 124

Après avoir passé des heures sur ce problème, aucune des réponses ci-dessus ne m'a aidé, alors j'ai trouvé un outil vraiment utile.

Tout d'abord, j'ai utilisé Fiddler 4 de Telerik pour étudier en détail mes demandes Web

Deuxièmement, j'ai découvert ce plugin utile pour Fiddler:

https://github.com/sunilpottumuttu/FiddlerGenerateHttpClientCode

Il va simplement générer le code C# pour vous. Un exemple était:

        var uriBuilder = new UriBuilder("test.php", "test");
        var httpClient = new HttpClient();

        var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uriBuilder.ToString());

        httpRequestMessage.Headers.Add("Host", "test.com");
        httpRequestMessage.Headers.Add("Connection", "keep-alive");
     //   httpRequestMessage.Headers.Add("Content-Length", "138");
        httpRequestMessage.Headers.Add("Pragma", "no-cache");
        httpRequestMessage.Headers.Add("Cache-Control", "no-cache");
        httpRequestMessage.Headers.Add("Origin", "test.com");
        httpRequestMessage.Headers.Add("Upgrade-Insecure-Requests", "1");
    //    httpRequestMessage.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
        httpRequestMessage.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
        httpRequestMessage.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        httpRequestMessage.Headers.Add("Referer", "http://www.translationdirectory.com/");
        httpRequestMessage.Headers.Add("Accept-Encoding", "gzip, deflate");
        httpRequestMessage.Headers.Add("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8");
        httpRequestMessage.Headers.Add("Cookie", "__utmc=266643403; __utmz=266643403.1537352460.3.3.utmccn=(referral)|utmcsr=google.co.uk|utmcct=/|utmcmd=referral; __utma=266643403.817561753.1532012719.1537357162.1537361568.5; __utmb=266643403; __atuvc=0%7C34%2C0%7C35%2C0%7C36%2C0%7C37%2C48%7C38; __atuvs=5ba2469fbb02458f002");

        var httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;

        var httpContent = httpResponseMessage.Content;
        string result = httpResponseMessage.Content.ReadAsStringAsync().Result;

Veuillez noter que j'ai dû mettre en commentaire deux lignes car ce plugin n'est pas encore totalement parfait mais il a quand même fait le travail.

AVIS DE NON-RESPONSABILITÉ : Je ne suis associé ni approuvé par Telerik ou l'auteur du plugin de quelque manière que ce soit.

5 votes

Il s'agit essentiellement de la même réponse que celle-ci, la seule partie concernant les cookies est cette dernière ajout d'un en-tête. Notez tous les avertissements dans cette réponse

4voto

KevM Points 1608

J'ai eu un problème similaire et pour mon application AspNetCore 3.1 les autres réponses à cette question ne fonctionnaient pas. J'ai découvert que configurer un HttpClient nommé dans mon Startup.cs et utiliser la propagation de l'en-tête Cookie fonctionnait parfaitement. Cela évite également toutes les préoccupations concernant la disposition correcte de votre gestionnaire et client. Notez que si la propagation des cookies de la requête n'est pas ce dont vous avez besoin (désolé Op) vous pouvez définir vos propres cookies lors de la configuration de la fabrique de clients.

Configurer les services avec IServiceCollection

services.AddHttpClient("MonClientNomme").AddHeaderPropagation();
services.AddHeaderPropagation(options =>
{
    options.Headers.Add("Cookie");
});

Configurer avec IApplicationBuilder

builder.UseHeaderPropagation();
  • Injectez l'IHttpClientFactory dans votre contrôleur ou middleware.
  • Créez votre client using var client = clientFactory.CreateClient("MonClientNomme");

0 votes

Est-ce que l'utilisation de services.AddHeaderPropagation(options, ajoute des cookies http aux requêtes suivantes?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X