Come posso impostare un cookie su HttpRequestMessage di HttpClient


247

Sto provando a utilizzare le API del Web HttpClientper inviare un post a un endpoint che richiede l'accesso sotto forma di un cookie HTTP che identifica un account (questo è solo qualcosa che è stato #ifdefeliminato dalla versione di rilascio).

Come faccio ad aggiungere un cookie a HttpRequestMessage?

Risposte:


374

Ecco come è possibile impostare un valore di cookie personalizzato per la richiesta:

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<string, string>("foo", "bar"),
        new KeyValuePair<string, string>("baz", "bazinga"),
    });
    cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
    var result = await client.PostAsync("/test", content);
    result.EnsureSuccessStatusCode();
}

2
il gestore può essere rimosso dall'uso dell'istruzione, verrà eliminato quando viene eliminato il client http.
Kimi,

17
Kimi è corretto, ma non dovresti nemmeno avvolgere il tuo HttpClient in un utilizzo. aspnetmonsters.com/2016/08/2016 08-27-27
Robert McLaws

9
ATTENZIONE: se si utilizza solo 1 istanza di HttpClient per eseguire diverse richieste, i cookie che utilizzano CookieContainer verranno memorizzati nella cache. È pericoloso per un utente ottenere i cookie da un altro utente.
Acaz Souza,

31
"HttpClient deve essere istanziato una volta e riutilizzato per tutta la vita di un'applicazione. Soprattutto nelle applicazioni server, la creazione di una nuova istanza HttpClient per ogni richiesta esaurirà il numero di socket disponibili sotto carichi pesanti ..." Da qui: asp .net / web-api / overview / advanced /…
SergeyT

4
@SergeyT quindi cosa si fa quando è necessario effettuare chiamate in sessioni separate alla stessa risorsa? :)
AgentFire,

337

La risposta accettata è il modo corretto per farlo nella maggior parte dei casi. Tuttavia, ci sono alcune situazioni in cui si desidera impostare manualmente l'intestazione del cookie. Normalmente se si imposta un'intestazione "Cookie", questa viene ignorata, ma perché l' HttpClientHandlerimpostazione predefinita utilizza la sua CookieContainerproprietà per i cookie. Se lo disabiliti, impostandolo UseCookiessu falsepuoi impostare manualmente le intestazioni dei cookie e appariranno nella richiesta, ad es

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

44
Inseguo da diversi giorni un errore in cui le richieste inviate con SendAsync non hanno inviato l'intestazione del cookie; questo mi ha aiutato a capire che, a meno che tu non abbia impostato UseCookies = false nel Gestore, non solo utilizzerà CookieContainer, ma ignorerà silenziosamente anche tutti i Cookie memorizzati nelle intestazioni della richiesta! Grazie mille!
Fernando Neira,

14
Questa risposta è estremamente utile per chiunque cerchi di utilizzare HttpClient come proxy!
cchamberlain,

3
Provando questo ora ... se funziona ... ti meriti un buon vecchio abbraccio canadese.
Maxime Rouiller il

11
ATTENZIONE: se si utilizza solo 1 istanza di HttpClient per eseguire diverse richieste, i cookie che utilizzano CookieContainer verranno memorizzati nella cache. È pericoloso per un utente ottenere i cookie da un altro utente.
Acaz Souza,

9
Quella cosa stupida dovrebbe fare un'eccezione quando qualcuno cerca di aggiungere un'intestazione "Cookie" invece di perderla silenziosamente. Mi è costato un'ora della mia vita. Grazie per la soluzione
stmax,

5

Dopo aver trascorso ore su questo problema, nessuna delle risposte sopra mi ha aiutato, quindi ho trovato uno strumento davvero utile.

In primo luogo, ho usato Fiddler 4 di Telerik per studiare in dettaglio le mie richieste Web

In secondo luogo, mi sono imbattuto in questo utile plug-in per Fiddler:

https://github.com/sunilpottumuttu/FiddlerGenerateHttpClientCode

Genererà semplicemente il codice C # per te. Un esempio è stato:

        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;

Nota che ho dovuto commentare due righe poiché questo plugin non è ancora del tutto perfetto, ma ha fatto comunque il lavoro.

NOTA BENE: Non sono associato o approvato da Telerik o dall'autore del plugin in ogni caso.


2
Questa è essenzialmente la stessa risposta di questa , l'unica parte che ha a che fare con i cookie è l'ultima aggiunta di un'intestazione. Nota tutti gli avvertimenti in quella risposta
George Mauer,

4

Per me la soluzione semplice funziona per impostare i cookie nell'oggetto HttpRequestMessage .

protected async Task<HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken = default(CancellationToken))
{
    requestMessage.Headers.Add("Cookie", $"<Cookie Name 1>=<Cookie Value 1>;<Cookie Name 2>=<Cookie Value 2>");

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

Si noti che la risposta accettata fa un sacco di più e gestisce molto di più le condizioni di bordo di questo. Può essere usato per fare cose come solo i cookie http o con ambito, i cookie multivalore, ecc. Ecc. La seconda risposta con il punteggio più alto propone lo stesso metodo di questo ma con un contesto e una spiegazione molto più numerosi
George Mauer

@GeorgeMauer potrebbe essere hai ragione. Entrambi creano httpClient da "HttpClient (gestore)". Nel mio caso sto creando _httpClient da httpClientPool.GetOrCreateHttpClient ()
Waqar UlHaq

1
Ma in realtà non lo mostri nella tua risposta né spieghi la differenza o i benefici (non è in realtà la domanda, ma non sono preoccupato per quello). Non sto cercando di essere scortese, è solo importante essere chiari su chi sarebbe stata utile questa risposta che non sarebbe stata aiutata meglio dagli altri.
George Mauer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.