Indy 10 - 手动添加 cookie
Indy 10 - add cookies manually
我可以使用“EditThisCookie”为 Google Chrome.
导出我的 cookie
导出如下所示:
"domain": ".whosebug.com",
"expirationDate": 1698322697,
"hostOnly": false,
"httpOnly": false,
"name": "_ga",
"path": "/",
"sameSite": "unspecified",
"secure": false,
"session": false,
"storeId": "0",
"value": "some",
"id": 1
现在,我想store/parse这个字符串到现有的TIdHTTP
Cookie 管理器。
如何使用 TIdCookie
将这些值添加到 Cookie 管理器?
这是我尝试过的方法,但没有成功:
procedure ImportCookies (JSONCookies: string; CookieManager: TIdCookieManager);
var
StringList: TStringList;
I : Integer;
InCookie : Boolean;
MyCookie: TidCookie;
function BoolStrToBool(s: string): Boolean;
begin
if Copy(UpperCase(Trim(s)), 1, 4) = 'TRUE' then Exit(True) else Exit(False);
end;
begin
InCookie := False;
StringList := TStringList.Create;
try
StringList.Text:= JSONCookies;
for I := 0 to StringList.Count - 1 do
begin
if Trim(StringList.Strings[i]) = '{' then
begin
InCookie := True;
MyCookie := CookieManager.CookieCollection.Add;
Continue;
end;
if (Trim(StringList.Strings[i]) = '}') or (Trim(StringList.Strings[i]) = '},') then
begin
InCookie := False;
Continue;
end;
if InCookie then
begin
if Copy(StringList.Strings[i], 1, 9) = '"domain":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 10, MaxInt);
MyCookie.Domain := GetBetween(StringList.Strings[i], '"', '"');
Continue;
end;
if Copy(StringList.Strings[i], 1, 11) = '"hostOnly":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 12, MaxInt);
MyCookie.HostOnly := BoolStrToBool(StringList.Strings[i]);
Continue;
end;
if Copy(StringList.Strings[i], 1, 11) = '"httpOnly":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 12, MaxInt);
MyCookie.HttpOnly := BoolStrToBool(StringList.Strings[i]);
Continue;
end;
if Copy (StringList.Strings[i], 1, 7) = '"name":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 8, MaxInt);
MyCookie.CookieName := GetBetween(StringList.Strings[i], '"', '"');
Continue;
end;
if Copy(StringList.Strings[i], 1, 7) = '"path":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 8, MaxInt);
MyCookie.Path := GetBetween(StringList.Strings[i], '"', '"');
Continue;
end;
if Copy(StringList.Strings[i], 1, 9) = '"secure":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 10, MaxInt);
MyCookie.Secure := BoolStrToBool(StringList.Strings[i]);
Continue;
end;
if Copy(StringList.Strings[i], 1, 8) = '"value":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 9, MaxInt);
MyCookie.Path := GetBetween(StringList.Strings[i], '"', '"');
Continue;
end;
end;
end;
finally
StringList.Free;
end;
end;
我不明白为什么我需要一个 TIdURI
实例 - 来源应该无关紧要,因为已经有一个目标域了?!
仅供参考,如果您使用实际的 JSON 解析器以及现有的 RTL/library 函数,您的代码可以大大简化,例如:
StrUtils.StartsText()
或 IdGlobal.TextStartsWith()
SysUtils.StrToBool()
SysUtils.AnsiExtractQuotedStr()
或 IdGlobalProtocols.UnquotedStr()
IdGlobal.PosInStrAray()
- 等等
或者,您可以简单地将导出的 cookie 数据重新格式化为标准的 HTTP cookie 格式,然后让 TIdCookieManager.AddServerCookie()
为您完成所有解析(但是您需要 TIdURI
)。
无论如何,TIdURI
由 TIdCookieManager
的解析器使用,因为 cookie 的某些方面需要根据其来源进行验证。例如,在确定 cookie 的路径时,或将其与 domain/host 匹配时,甚至只是知道 HostOnly
cookie 的原始主机是什么,或者是否通过接收到 HttpOnly
cookie HTTP 等。cookie 处理、接收 cookie 时以及向服务器发送 cookie 时都有规则,这些规则与 cookie 的来源相关URL。
在您的情况下,由于您正在跳过 TIdCookieManager.AddServerCookie()
,您实际上并不需要 TIdURI
,因为 Chrome 已经为您完成了繁重的处理。
但是,AddServerCookie()
确实做了一件你没有做的事情,那就是它将 TIdCookie
添加到内部 TIdCookies
列表中,稍后在决定使用哪些 cookie 时会使用该列表在 TIdHTTP
个请求中发送回哪些服务器(参见 TIdCookieManager.GenerateClientCookies()
)。
因此,仅调用 TIdCookieManager.CookieCollection.Add()
是不够的,它只会创建 TIdCookie
对象。您还需要调用 TIdCookieManager.CookieCollection.AddCookie()
- 它也需要一个 TIdURI
,尽管这个是可选的,而 AddServerCookie()
中的那个是必需的。
所以,试试这样的东西:
procedure ImportCookies(JSONCookies: string; CookieManager: TIdCookieManager);
var
StringList: TStringList;
I : Integer;
MyCookie: TidCookie;
S, FieldName, FieldValue: string;
procedure AddMyCookieIfReady;
begin
if MyCookie <> nil then
begin
if not CookieManager.CookieCollection.AddCookie(MyCookie, nil) then
begin
MyCookie.Collection := nil;
MyCookie.Free;
end;
MyCookie = nil;
end;
end;
begin
StringList := TStringList.Create;
try
StringList.Text := JSONCookies;
MyCookie := nil;
for I := 0 to StringList.Count - 1 do
begin
s := Trim(StringList.Strings[I]);
if s = '{' then
begin
AddMyCookieIfReady;
MyCookie := CookieManager.CookieCollection.Add;
Continue;
end;
if TextStartsWith(s, '}') then
begin
AddMyCookieIfReady;
Continue;
end;
if (MyCookie = nil) or (not TextStartsWith(s, '"')) then
Continue;
Delete(s, 1, 1);
FieldName := Fetch(s, '"');
Fetch(s, ':');
FieldValue := UnquotedStr(TrimLeft(s));
case PosInStrArray(FieldName, ['domain', 'hostOnly', 'httpOnly', 'name', 'path', 'secure', 'value'], False) of
0: begin
if TextStartsWith(FieldValue, '.') then Delete(FieldValue, 1, 1);
MyCookie.Domain := FieldValue;
end;
1: MyCookie.HostOnly := StrToBool(FieldValue);
2: MyCookie.HttpOnly := StrToBool(FieldValue);
3: MyCookie.CookieName := FieldValue;
4: MyCookie.Path := FieldValue;
5: MyCookie.Secure := StrToBool(FieldValue);
6: MyCookie.Value := FieldValue;
end;
end;
AddMyCookieIfReady;
finally
StringList.Free;
end;
end;
我可以使用“EditThisCookie”为 Google Chrome.
导出我的 cookie导出如下所示:
"domain": ".whosebug.com",
"expirationDate": 1698322697,
"hostOnly": false,
"httpOnly": false,
"name": "_ga",
"path": "/",
"sameSite": "unspecified",
"secure": false,
"session": false,
"storeId": "0",
"value": "some",
"id": 1
现在,我想store/parse这个字符串到现有的TIdHTTP
Cookie 管理器。
如何使用 TIdCookie
将这些值添加到 Cookie 管理器?
这是我尝试过的方法,但没有成功:
procedure ImportCookies (JSONCookies: string; CookieManager: TIdCookieManager);
var
StringList: TStringList;
I : Integer;
InCookie : Boolean;
MyCookie: TidCookie;
function BoolStrToBool(s: string): Boolean;
begin
if Copy(UpperCase(Trim(s)), 1, 4) = 'TRUE' then Exit(True) else Exit(False);
end;
begin
InCookie := False;
StringList := TStringList.Create;
try
StringList.Text:= JSONCookies;
for I := 0 to StringList.Count - 1 do
begin
if Trim(StringList.Strings[i]) = '{' then
begin
InCookie := True;
MyCookie := CookieManager.CookieCollection.Add;
Continue;
end;
if (Trim(StringList.Strings[i]) = '}') or (Trim(StringList.Strings[i]) = '},') then
begin
InCookie := False;
Continue;
end;
if InCookie then
begin
if Copy(StringList.Strings[i], 1, 9) = '"domain":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 10, MaxInt);
MyCookie.Domain := GetBetween(StringList.Strings[i], '"', '"');
Continue;
end;
if Copy(StringList.Strings[i], 1, 11) = '"hostOnly":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 12, MaxInt);
MyCookie.HostOnly := BoolStrToBool(StringList.Strings[i]);
Continue;
end;
if Copy(StringList.Strings[i], 1, 11) = '"httpOnly":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 12, MaxInt);
MyCookie.HttpOnly := BoolStrToBool(StringList.Strings[i]);
Continue;
end;
if Copy (StringList.Strings[i], 1, 7) = '"name":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 8, MaxInt);
MyCookie.CookieName := GetBetween(StringList.Strings[i], '"', '"');
Continue;
end;
if Copy(StringList.Strings[i], 1, 7) = '"path":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 8, MaxInt);
MyCookie.Path := GetBetween(StringList.Strings[i], '"', '"');
Continue;
end;
if Copy(StringList.Strings[i], 1, 9) = '"secure":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 10, MaxInt);
MyCookie.Secure := BoolStrToBool(StringList.Strings[i]);
Continue;
end;
if Copy(StringList.Strings[i], 1, 8) = '"value":' then
begin
StringList.Strings[i] := Copy(StringList.Strings[i], 9, MaxInt);
MyCookie.Path := GetBetween(StringList.Strings[i], '"', '"');
Continue;
end;
end;
end;
finally
StringList.Free;
end;
end;
我不明白为什么我需要一个 TIdURI
实例 - 来源应该无关紧要,因为已经有一个目标域了?!
仅供参考,如果您使用实际的 JSON 解析器以及现有的 RTL/library 函数,您的代码可以大大简化,例如:
StrUtils.StartsText()
或IdGlobal.TextStartsWith()
SysUtils.StrToBool()
SysUtils.AnsiExtractQuotedStr()
或IdGlobalProtocols.UnquotedStr()
IdGlobal.PosInStrAray()
- 等等
或者,您可以简单地将导出的 cookie 数据重新格式化为标准的 HTTP cookie 格式,然后让 TIdCookieManager.AddServerCookie()
为您完成所有解析(但是您需要 TIdURI
)。
无论如何,TIdURI
由 TIdCookieManager
的解析器使用,因为 cookie 的某些方面需要根据其来源进行验证。例如,在确定 cookie 的路径时,或将其与 domain/host 匹配时,甚至只是知道 HostOnly
cookie 的原始主机是什么,或者是否通过接收到 HttpOnly
cookie HTTP 等。cookie 处理、接收 cookie 时以及向服务器发送 cookie 时都有规则,这些规则与 cookie 的来源相关URL。
在您的情况下,由于您正在跳过 TIdCookieManager.AddServerCookie()
,您实际上并不需要 TIdURI
,因为 Chrome 已经为您完成了繁重的处理。
但是,AddServerCookie()
确实做了一件你没有做的事情,那就是它将 TIdCookie
添加到内部 TIdCookies
列表中,稍后在决定使用哪些 cookie 时会使用该列表在 TIdHTTP
个请求中发送回哪些服务器(参见 TIdCookieManager.GenerateClientCookies()
)。
因此,仅调用 TIdCookieManager.CookieCollection.Add()
是不够的,它只会创建 TIdCookie
对象。您还需要调用 TIdCookieManager.CookieCollection.AddCookie()
- 它也需要一个 TIdURI
,尽管这个是可选的,而 AddServerCookie()
中的那个是必需的。
所以,试试这样的东西:
procedure ImportCookies(JSONCookies: string; CookieManager: TIdCookieManager);
var
StringList: TStringList;
I : Integer;
MyCookie: TidCookie;
S, FieldName, FieldValue: string;
procedure AddMyCookieIfReady;
begin
if MyCookie <> nil then
begin
if not CookieManager.CookieCollection.AddCookie(MyCookie, nil) then
begin
MyCookie.Collection := nil;
MyCookie.Free;
end;
MyCookie = nil;
end;
end;
begin
StringList := TStringList.Create;
try
StringList.Text := JSONCookies;
MyCookie := nil;
for I := 0 to StringList.Count - 1 do
begin
s := Trim(StringList.Strings[I]);
if s = '{' then
begin
AddMyCookieIfReady;
MyCookie := CookieManager.CookieCollection.Add;
Continue;
end;
if TextStartsWith(s, '}') then
begin
AddMyCookieIfReady;
Continue;
end;
if (MyCookie = nil) or (not TextStartsWith(s, '"')) then
Continue;
Delete(s, 1, 1);
FieldName := Fetch(s, '"');
Fetch(s, ':');
FieldValue := UnquotedStr(TrimLeft(s));
case PosInStrArray(FieldName, ['domain', 'hostOnly', 'httpOnly', 'name', 'path', 'secure', 'value'], False) of
0: begin
if TextStartsWith(FieldValue, '.') then Delete(FieldValue, 1, 1);
MyCookie.Domain := FieldValue;
end;
1: MyCookie.HostOnly := StrToBool(FieldValue);
2: MyCookie.HttpOnly := StrToBool(FieldValue);
3: MyCookie.CookieName := FieldValue;
4: MyCookie.Path := FieldValue;
5: MyCookie.Secure := StrToBool(FieldValue);
6: MyCookie.Value := FieldValue;
end;
end;
AddMyCookieIfReady;
finally
StringList.Free;
end;
end;