I have Indy 10.6.2.5366 and delphi Tokyo 10.2 update 3.
In a response to an HTTPS POST
, the CookieManager states there are no cookies, but when i do the same request in postman, there's a Cookie called "ROUTEID" in the response.
but when i do the exactly same request on delphi, there is no "ROUTEID" cookie.
i need to persist the cookies because they have authentication information that i need to send in the subsequent requests, as Remy Lebeau states in this post.
I Must be doing something wrong, because in this other post, remy says that TCookieManager were completely re-written from scratch, but what i'm missing?
I've notice that postman shows 10 headers in the response, but delphi shows only 8 in the TIdHTTP.Response.RawHeaders
I know that the response code of my request is 401, but even with an unauthorized error, there's a cookie in the response.
finally, here's my code:
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;
In a response to an HTTPS POST, the CookieManager states there are no cookies, but when i do the same request in postman, there's a Cookie called "ROUTEID" in the response ... but when i do the exactly same request on delphi, there is no "ROUTEID" cookie.
Then the problem is not with Indy itself. The server is not sending a cookie to begin with.
I've notice that postman shows 10 headers in the response, but delphi shows only 8 in the TIdHTTP.Response.RawHeaders
That means the server is sending a different response to different user agents. See this question that I answered just yesterday, which suffered from a similar problem. But in a nutshell:
Many servers are sensitive to the requesting agent, where they send different data to different agents. It is not uncommon for such servers to reject/not recognize Indy's default
User-Agent
value....
When you are comparing curl [or, in this case, postman] requests to other HTTP libraries, you should always strive to make the requests be as close to identical as possible to eliminate any possible differences that can confuse servers. And when there are behavior differences between similar requests, it is typically the
User-Agent
[request header] at fault.
I see you are setting the TIdHTTP.Request.UserAgent
property to a value that mimics Firefox. Do you have the same problem if you set it to mimic Postman instead? I believe Postman's default User-Agent
is something like PostmanRuntime/<version>
. Do you have the same problem if you configure Postman to use the same Firefox User-Agent
value that TIdHTTP
is using?
On a side note, not related to your cookie issue, but with your presented code in general:
you should not be calling IdOpenSSLSetLibPath()
on every HTTP request. Call it one time, preferably at app startup.
do not use the SSLIOHandler's SSLOptions.Method
and SSLOptions.SSLVersions
properties together. They are mutually exclusive, setting one updates the other. By setting the Method
to sslvSSLv23
, you are enabling both SSL v2-v3 in addition to TLS v1.0-1.2. Do not enable SSL anymore. Stick with just the SSLVersions
property by itself.
do not set the TIdHTTP.Response.ContentType
property when sending a request. That is just useless.
the TIdHTTP.Request.CustomHeaders.FoldLines
property should be False, as the HTTP protocol no longer supports header folding as of RFC 7230.
do not set the TIdHTTP.Request.AcceptEncoding
property manually, unless you are prepared to decode the raw response body manually. Indy natively supports gzip
and deflate
compression via the TIdHTTP.Compressor
property, but it does not support br
at this time. You are giving the server permission to compress the response in a way that TIdHTTP
will not be able to decompress automatically (case in point, your screenshot shows the response is gzip-compressed). The correct approach is to enable the Compressor
and let TIdHTTP
manage the AcceptEncoding
for you based on the compressor's actual capabilities.
you are leaking the TIdCookieManager
object. TIdHTTP
does not take ownership of a user-supplied CookieManager. If you don't supply one, TIdHTTP
will simply create one internally and take ownership of it.