Indy TIdHTTP, по-видимому, отсутствует файл cookie сервера при почтовом запросе?

У меня Indy 10.6.2.5366 и Delphi Tokyo 10.2 с обновлением 3.

В ответ на HTTPS POST CookieManager сообщает, что файлов cookie нет, но когда я делаю тот же запрос в почтальоне, в ответе появляется файл cookie с именем «ROUTEID».

но когда я делаю тот же запрос в Delphi, файл cookie «ROUTEID» отсутствует.

мне нужно сохранить файлы cookie, потому что они содержат информацию для аутентификации, которую мне нужно отправлять в последующих запросах, как утверждает Реми Лебо в этом посте.

Должно быть, я делаю что-то не так, потому что в этом другом посте Реми говорит, что TCookieManager был полностью переписан с нуля, но что мне не хватает?

Я заметил, что почтальон показывает 10 заголовков в ответе, а Delphi показывает только 8 в TIdHTTP.Response.RawHeaders

Я знаю, что код ответа моего запроса 401, но даже при несанкционированной ошибке в ответе присутствует куки.

наконец, вот мой код:

procedure TestMethod(AUrl, ABody: string);
var
  HTTP: TIdHTTP;
  SSL: TIdSSLIOHandlerSocketOpenSSL;
  LStreamRequestBody: TStringStream;
  LReturnBody: string;
  LCookieList: TIdCookieList;
  n: Integer;
begin

  HTTP := TIdHTTP.Create(nil);
  SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  LStreamRequestBody := TStringStream.Create(ABody, TEncoding.UTF8);
  try
    IdOpenSSLSetLibPath(Utils.Global.SSLLibPath);

    SSL.SSLOptions.Method := sslvSSLv23;
    SSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1];
    SSL.SSLOptions.Method := sslvSSLv23;

    HTTP.IOHandler := SSL;
    HTTP.Response.ContentType := 'application/json;charset=utf-8';
    HTTP.Request.CustomHeaders.FoldLines := True;
    HTTP.Request.Accept := '*/*';
    HTTP.Request.ContentType := 'application/json';
    HTTP.Request.Connection := 'keep-alive';
    HTTP.Request.AcceptEncoding := 'gzip, deflate, br';
    HTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';

    HTTP.CookieManager := TIdCookieManager.Create(nil);
    HTTP.AllowCookies := True;
    HTTP.HandleRedirects := True;

    try
      LReturnBody := HTTP.Post(AUrl, LStreamRequestBody);
    Except
      on e: EIdHTTPProtocolException do
      begin
        LCookieList := HTTP.CookieManager.CookieCollection.LockCookieList(caRead);
        try
          for n := 0 to LCookieList.Count - 1 do
          begin

          end;
        finally
          HTTP.CookieManager.CookieCollection.UnlockCookieList(caRead);
        end;
      end;
    end;
  finally
    LStreamRequestBody.Free;
    HTTP.Free;
    SSL.Free;
  end;
end;

1
84
1

Ответ:

Решено

В ответ на HTTPS POST CookieManager сообщает, что файлов cookie нет, но когда я делаю тот же запрос в почтальоне, в ответе появляется файл cookie с именем «ROUTEID»... но когда я делаю точно такой же запрос в Delphi, нет файла cookie «ROUTEID».

Тогда проблема не в самом Инди. Сервер изначально не отправляет файлы cookie.

Я заметил, что почтальон показывает 10 заголовков в ответе, но Delphi показывает только 8 в TIdHTTP.Response.RawHeaders.

Это означает, что сервер отправляет разные ответы разным пользовательским агентам. Смотрите этот вопрос , на который я ответил буквально вчера, который страдал от подобной проблемы. Но в двух словах:

Многие серверы чувствительны к запрашивающему агенту и отправляют разные данные разным агентам. Такие серверы нередко отклоняют/не распознают значение Indy по умолчанию User-Agent.

...

Когда вы сравниваете запросы Curl [или, в данном случае, Postman] с другими HTTP-библиотеками, вы всегда должны стремиться к тому, чтобы запросы были как можно более идентичными, чтобы исключить любые возможные различия, которые могут сбить с толку серверы. А когда между похожими запросами существуют различия в поведении, обычно виноват User-Agent [заголовок запроса].

Я вижу, вы устанавливаете для свойства TIdHTTP.Request.UserAgent значение, имитирующее Firefox. Возникнет ли у вас та же проблема, если вместо этого вы настроите имитацию Почтальона? Я считаю, что значение User-Agent Postman по умолчанию — это что-то вроде PostmanRuntime/<version>. Возникнет ли у вас та же проблема, если вы настроите Postman на использование того же значения Firefox User-Agent, что и TIdHTTP?


Кстати, это связано не с вашей проблемой с файлами cookie, а с представленным вами кодом в целом:

  • вам не следует вызывать IdOpenSSLSetLibPath() при каждом HTTP-запросе. Вызовите его один раз, желательно при запуске приложения.

  • не используйте свойства SSLOptions.Method и SSLOptions.SSLVersions SSLIOHandler вместе. Они являются взаимоисключающими, установка одного обновляет другой. Установив Method на sslvSSLv23, вы включаете SSL v2–v3 в дополнение к TLS v1.0–1.2. Больше не включайте SSL. Остановитесь только на свойстве SSLVersions.

  • не устанавливайте свойство TIdHTTP.Response.ContentType при отправке запроса. Это просто бесполезно.

  • свойство TIdHTTP.Request.CustomHeaders.FoldLines должно иметь значение False, поскольку протокол HTTP больше не поддерживает свертывание заголовков, начиная с RFC 7230.

  • не устанавливайте свойство TIdHTTP.Request.AcceptEncoding вручную, если вы не готовы декодировать необработанное тело ответа вручную. Indy изначально поддерживает сжатие gzip и deflate через свойство TIdHTTP.Compressor, но в настоящее время не поддерживает br. Вы даете серверу разрешение на сжатие ответа таким образом, чтобы TIdHTTP не могло быть распаковано автоматически (например, на вашем снимке экрана показано, что ответ сжат с помощью gzip). Правильный подход — включить Compressor и позволить TIdHTTP управлять AcceptEncoding за вас, исходя из реальных возможностей компрессора.

  • вы сливаете объект TIdCookieManager. TIdHTTP не становится владельцем предоставленного пользователем CookieManager. Если вы его не предоставите, TIdHTTP просто создаст его внутри компании и возьмет на себя ответственность за него.