Як встановити файл cookie на HttpClient в HttpRequestMessage


247

Я намагаюся використовувати веб-api, HttpClientщоб зробити публікацію до кінцевої точки, яка вимагає входу у вигляді файлу cookie HTTP, який ідентифікує обліковий запис (це лише те, що #ifdefвимкнено з версії версії).

Як додати печиво до файлу HttpRequestMessage?

Відповіді:


374

Ось як можна встановити спеціальне значення файлу cookie для запиту:

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
обробник може бути видалений з використання оператора, він буде видалений, коли клієнт http розміщений.
Кімі

17
Кімі правильний, але також не слід впаковувати свій HttpClient у використанні. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Роберт

9
ПОПЕРЕДЖЕННЯ. Якщо ви використовуєте лише 1 екземпляр HttpClient, щоб зробити кілька запитів, файли cookie, що використовують CookieContainer, збираються в кешування. Небезпечно для користувача отримати печиво від іншого користувача.
Acaz Souza

31
"HttpClient призначений для одноразової реєстрації та повторного використання протягом усього життя програми. Особливо в серверних додатках. Створення нового екземпляра HttpClient для кожного запиту вичерпає кількість розеток, доступних при великих навантаженнях ..." Звідси: asp .net / web-api / огляд / розширений /…
SergeyT

4
@SergeyT, що робити, коли йому потрібно робити дзвінки на окремому сеансі на один і той же ресурс? :)
AgentFire

337

Загальноприйнятий відповідь правильний спосіб зробити це в більшості випадків. Однак є деякі ситуації, коли ви хочете встановити заголовок файлу cookie вручну. Зазвичай, якщо встановити заголовок "Cookie", він ігнорується, але це тому, що HttpClientHandlerза замовчуванням використовується його CookieContainerвластивість для файлів cookie. Якщо відключити , що потім, встановивши UseCookiesдля falseвас може встановити заголовки куки вручну , і вони будуть з'являтися в запиті, наприклад ,

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
Я кілька днів переслідував помилку, коли запити, надіслані за допомогою SendAsync, не надсилали заголовок файлу cookie; це допомогло мені зрозуміти, що, якщо ви не встановите UseCookies = false у обробнику, він не лише використовуватиме CookieContainer, але й мовчки ігнорує будь-який файл cookie, що зберігається у заголовках запиту! Дуже дякую!
Фернандо Нейра

14
Ця відповідь надзвичайно корисна для тих, хто намагається використовувати HttpClient як проксі!
cchamberlain

3
Спробуй це зараз ... якщо це спрацює ... ти заслуговуєш на добрий канадський обійм.
Максим Рулер

11
ПОПЕРЕДЖЕННЯ. Якщо ви використовуєте лише 1 екземпляр HttpClient, щоб зробити кілька запитів, файли cookie, що використовують CookieContainer, збираються в кешування. Небезпечно для користувача отримати печиво від іншого користувача.
Acaz Souza

9
Ця дурна річ повинна кинути виняток, коли хтось намагається додати заголовок "Cookie", а не мовчки втрачати його. Коштує мене година мого життя. Дякую за рішення.
stmax

5

Провівши години на це питання, жодна з наведених відповідей мені не допомогла, тому я знайшов справді корисний інструмент.

По-перше, я використовував Fiddler 4 Telerik, щоб детально вивчити свої запити в Інтернеті

По-друге, я натрапив на цей корисний плагін для Fiddler:

https://github.com/sunilpottumuttu/FiddlerGenerateHttpClientCode

Він просто створить код # для вас. Приклад:

        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;

Зауважте, що мені довелося прокоментувати два рядки, оскільки цей плагін ще не зовсім ідеальний, але він все-таки зробив цю роботу.

ВІДМОВА ВІДПОВІДАЛЬНОСТІ: Я жодним чином не асоціююсь або не схвалюю ні Telerik, ні автора плагіна.


2
Це по суті та сама відповідь, що і ця , єдина частина, що стосується файлів cookie - це останнє додавання заголовка. Зверніть увагу на всі застереження у цій відповіді
Джордж Мауер

4

Для мене просте рішення працює для встановлення файлів cookie в об’єкт 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);
}

Зауважте, що прийнята відповідь робить на тонну більше і обробляє набагато більше крайових умов, ніж ця. З його допомогою можна робити такі речі, як лише http або масштабні файли cookie, багатозначні файли cookie тощо. Друга відповідь, що найбільше оцінюється, пропонує той самий метод, що і цей, але з набагато більшим контекстом і поясненнями
Джордж Мауер

@GeorgeMauer, можливо, ти маєш рацію. Вони обидва створюють httpClient з "HttpClient (обробник)". У моєму випадку я створюю _httpClient з httpClientPool.GetOrCreateHttpClient ()
Waqar UlHaq

1
Але ви насправді не показуєте, що у своїй відповіді не пояснюєте різницю чи переваги (це теж насправді не питання, але я не переживаю з цього приводу). Я не намагаюся бути грубим, просто важливо зрозуміти, хто ця відповідь буде корисним, щоб краще не допомагали інші.
Джордж Мауер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.