我想在CloudFlare
框架中创建一个Firemonkey
客户端。对于那些不知道的人,CloudFlare可以作为任何拥有网站的人的CDN。他们有一个可用的API,和许多Web API一样,他们使用JSON
和基于令牌的系统。它需要帐户电子邮件地址和帐户令牌才能访问API。它运行在HTTPS上,您可以想象,尝试通过HTTP /非SSL访问API只会产生空结果。
我想创建的应用程序将作为一体化管理工具,旨在消除我使用Web浏览器管理我的CloudFlare设置的需要。我有最基本的问题; SSL POST。请参阅,我可以通过网络浏览器提交API请求并获取结果列表(例如https://www.cloudflare.com/api_json.html?a=stats&z=DOMAIN&u=EMAIL&tkn=TOKEN
- 出于显而易见的原因删除了个人详细信息),但我不确定如何获得这些相同的结果(或Firemonkey中的API的任何结果。
我已经安装了SSL Overbyte ICS
,以及基本的捆绑Indy
组件,但我很难开始使用它。我需要通过HTTPS / SSL将参数列表发布到https://www.cloudflare.com/api_json.html
,但我很少知道从哪里开始。我已经看到了一些围绕SO的各种示例,主要是使用ICS,但我一直无法找到任何具体的发布多个参数,我应该如何格式化等等。
我尝试的一个例子是使用ICS TSSLHttpCli
,将我的参数编写为单个字符串(即a=stats&z=DOMAIN&u=EMAIL&tkn=TOKEN
),将其写入SendStream
的{{1}},寻求TSSLHttpCli
,设置网址(即0,0
),然后调用https://www.cloudflare.com/api_json.html?
方法。但是,这给了我Post
。这是我尝试过的代码(虽然我用通用值替换了个人详细信息);
Connection aborted on request
var
Data : AnsiString;
RcvStrm, SndStrm : TMemoryStream;
begin
SndStrm := TMemoryStream.Create;
RcvStrm := TMemoryStream.Create;
Data := '?a=stats&z=MYDOMAIN&u=MYEMAIL&tkn=MYTOKEN';
SslHttpCli.SendStream := SndStrm;
SslHttpCli.SendStream.Write(Data[1],Length(Data));
SslHttpCli.SendStream.Seek(0,0);
Memo1.Lines.LoadFromStream(SndStrm);
ShowMessage('Waiting!');
SslHttpCli.RcvdStream := RcvStrm;
SslHttpCli.URL := 'https://www.cloudflare.com/api_json.html';
SslHttpCli.Post;
Memo1.Lines.Clear;
Memo1.Lines.LoadFromStream(RcvStrm);
Memo1.Lines.Add('.....');
RcvStrm.Free;
SndStrm.Free;
ShowMessage('Complete!');
end;
程序只是提供一个视觉中断,所以我可以看到每次流中的数据。调用ShowMessage
时,我会按预期在备忘录中收到Memo1.Lines.LoadFromStream(SndStrm);
的内容。
当我打电话给Data
时,我希望它能从API中添加返回结果,然后在它下面添加5个点。但是,这种情况不会发生,而且我收到的消息显然与问题有关。我假设我没有正确设置数据,但我只是不确定在尝试发布之前我应该如何格式化它。我甚至将Memo1.Lines.LoadFromStream(RcvStrm);
以下的所有内容评论到最后,看看是否在备忘录上调用了Memo1.Lines.LoadFromStream(RcvStrm);
程序,但备忘录的内容与我调用{{1}时的内容保持一致}}。最后的Clear
也没有被调用。
我最初尝试使用String而不是AnsiString,但这只是输出Data的第一个字符而不是整个字符串。
可能有很多原因导致它无法正常工作(API访问的所有细节都是正确的,所以这是代码的问题),但我需要有更多经验和知识的人指出我正确的方向。
我的网络编码知识有限,到目前为止我只处理Delphi中的基本SQL和FTP。一旦我完成了这一步,我仍然需要使用已解析的JSON,但是现在,任何人都可以协助我完成这项工作,这样我就可以开始了吗?
答案 0 :(得分:0)
我注意到你似乎用GET请求解决了这个问题,但我注意到你的POST请求有两个直接问题:
作为Runner建议,放下'?'在你的数据中。 '?'仅在将参数附加到GET请求中的URL时使用。
您永远不会设置HTTP请求的内容类型(应为application/x-www-form-urlencoded
)。您可以使用以下代码执行此操作:
SSLHttpCli.ContentTypePost := 'application/x-www-form-urlencoded';
只是一个有用的想法。我检查了https://www.cloudflare.com/docs/client-api.html,他们提到接受了POST请求。服务器可能会拒绝具有任何其他内容类型的请求。
如果您需要通过POST请求联系其他API并希望使用Overbyte Components,那么只需要考虑一下。
希望信息有用!
答案 1 :(得分:0)
尝试一下;
SndStrm := TMemoryStream.Create;
RcvStrm := TMemoryStream.Create;
Data := 'a=stats&z=MYDOMAIN&u=MYEMAIL&tkn=MYTOKEN';
SndStrm.Write(Data[1], Length(Data));
SndStrm.Seek(0, 0);
SslHttpCli.SendStream := SndStrm;
答案 2 :(得分:-1)
我只是想出来了。为了其他新的HTTP POST,这就是我所做的;
1)将TIdHTTP
放到您的表单上(Indy
的一部分)
2)将TIdSSLIOHandlerSocketOpenSSL
放到您的表格上(也是Indy的一部分)
3)将IOHandler
的{{1}}值设置为IdHTTP
(默认名称)
4)将IdSSLIOHandlerSocketOpenSSL1
放到您的表单上(在示例中,它称为TMemo
)
5)使用下一个块中的代码在事件处理程序中进行POST(例如button.onclick);
Memo1
随意删除var
Params, RcvStrng : TStringStream;
begin
RcvStrng := TStringStream.Create;
Params := TStringStream.Create;
Params.WriteString('a=stats');
Params.WriteString('z=MYDOMAIN');
Params.WriteString('u=MYEMAIL');
Params.WriteString('tkn=MYTOKEN');
IdHTTP.Post('https://www.cloudflare.com/api_json.html',Params,RcvStrng);
ShowMessage('Waiting!');
Memo1.Lines.Clear;
Memo1.Text := RcvStrng.DataString;
Params.Free;
ShowMessage('Complete!');
end;
程序。还有一些工作要做,因为我从API得到了错误响应,但它现在在工作范围内(而不是错误输出)。其余API请求的格式类似,只需添加,删除或修改ShowMessage
即可使用您需要发送的请求。
不需要Params
,Synapse
或任何其他“非捆绑”组件来使其正常工作,因为Indy完美地完成了这项工作,假设您设置了IOHandler并使用{{1正确的。
我很高兴任何人都可以通过CloudFlare特有的额外点来为此做出贡献,并会尝试适当地编辑答案。
CloudFlare特定备注
我对此进行了更多调查,对于CloudFlare,我必须直接发布到完全限定的URL(即带有以下参数的API URL,与通过浏览器访问它的方式完全相同)或者在原始问题中提到; ICS
)。其余代码保持不变,但可以简单地提交一个空StringStream来代替TStringStream
。在没有指定https://www.cloudflare.com/api_json.html?a=stats&z=DOMAIN&u=EMAIL&tkn=TOKEN
的情况下提交不同的Params
重载版本只会返回没有结果。