【发布时间】:2018-09-11 19:25:06
【问题描述】:
我在 PHP 中创建了一个简单的 API,用于从 GET/POST 请求中接收一些变量并将其发布到第三方 GraphQL API。但我在内容编码方面遇到了问题。
应用程序以这种方式工作:
Delphi 5 桌面应用程序向我的 PHP API 发送带有一些变量的简单 GET 或 POST,我的 PHP API 向第三方 GraphQL API 发出查询请求。
我发送的 GraphQL 是:
query {
node(id: 1){
... on Organization{
fullname
entities(type: STUDENT, search: "Some Student Name"){
nodes{
dbId
fullname
eid
}
}
}
}
}
请求网址示例为:
当我将请求 URL 复制并粘贴到浏览器时,在命令提示符 cURL 上调用它,工作正常。
但是,当 Delphi 5 调用它时,它用很多“+”(加号)破坏了我的查询字符串:
Syntax Error GraphQL request (1:6) Cannot parse the unexpected character "+".
1: query+%7B%0D%0A++node%28id%3A+1%29%7B%0D%0A++++...+on+Organization%7B%0D%0A++++++fullname%0D%0A++++++entities%28type%3A+STUDENT%2C+search%3A+%22Some Student Name%22%29%7B%0D%0A++++++++nodes%7B%0D%0A++++++++++dbId%0D%0A++++++++++fullname%0D%0A++++++++++eid%0D%0A++++++++%7D%0D%0A++++++%7D%0D%0A++++%7D%0D%0A++%7D%0D%0A%7D
^
Delphi 5 应用程序使用 TidHTTP 组件来完成它。代码如下:
procedure TForm1.ExportaClassApp(prID : Integer; prNumBoleto, prLinhaDigitavel : String);
const cUrl = 'http://api-link/request.php?';
cToken = 'xyzwsa';
cTipo = 'boleto';
cE_Comercial = #138; (* equivalent to & *)
var sSQL : String;
qryPesquisa : TADOQuery;
oHTTP : TIdHTTP;
sRetornoClassApp : String;
HTTPClient : TidHTTP;
Lista : TStringStream;
sParametros : String;
Url_Completa : String;
sToken : String;
sId : String;
sTipo : String;
sMatricula : String;
sNome_Aluno : String;
sNome_Responsavel : String;
sDescricao : String;
sNumBoleto : String;
sVencimento : String;
sValor : String;
sLinhaDigitavel : String;
begin
oHTTP := TIdHTTP.Create(Application);
HTTPClient := TidHTTP.Create(Application);;
sDescricao := '';
sDescricao := Copy(sDescricao,1, length(sDescricao) - 2);
sToken := 'token=' + cToken;
sId := '&id=' + IntToStr(prId);
sTipo := '&tipo=' + cTipo;
sMatricula := '&mat=' + '123456';
sNome_Aluno := '&nome_aluno=' + 'Some Student Name';
sNome_Responsavel := '&nome_responsavel=' + 'Another Name';
sDescricao := '&titulo=' + 'Just a test';
sNumBoleto := '&numero=' + prNumBoleto;
sVencimento := '&venc=' + '2018-04-02';
sValor := '&valor=' + FloatToStr(843 * 100);
sLinhaDigitavel := '&linha=' + prLinhaDigitavel;
sParametros := sToken + sId + sTipo + sMatricula + sNome_Aluno + sNome_Responsavel + sDescricao + sNumBoleto + sVencimento + sValor + sLinhaDigitavel;
Url_Completa := cUrl + sPArametros;
Url_Completa := StringReplace(Url_Completa,' ','%20',[rfReplaceAll, rfIgnoreCase]);
if edtContentType.Text <> '' then
oHTTP.Request.ContentType := edtContentType.Text
else
oHTTP.Request.ContentType := '';
if edtContentEncoding.Text <> '' then
oHTTP.Request.ContentEncoding := edtContentEncoding.Text
else
oHTTP.Request.ContentEncoding := '';
sRetornoClassApp := oHTTP.URL.URLDecode(oHTTP.Get(Url_Completa));
btnLimparClick(Self);
mmoEnvio.Text := Url_Completa;
mmoRetorno.Text := sRetornoClassApp;
FreeAndNil(oHTTP);
end;
这是浏览器/cURL 请求/响应标头(有效):
Array
(
[0] => POST /graphql HTTP/1.1
[1] => Host: joy.classapp.co
[2] => User-Agent: PHP Curl/1.6 (+https://github.com/php-mod/curl)
[3] => Accept: */*
[4] => Content-Length: 400
[5] => Content-Type: application/x-www-form-urlencoded
)
Array
(
[0] => HTTP/1.1 200 OK
[1] => Access-Control-Allow-Origin: *
[2] => Content-Type: application/json; charset=utf-8
[3] => Date: Mon, 02 Apr 2018 14:37:19 GMT
[4] => ETag: W/"4d-r2dRUM/0NEHToQUzFDAesWSzSWY"
[5] => Server: nginx/1.12.1
[6] => X-Content-Type-Options: nosniff
[7] => X-DNS-Prefetch-Control: off
[8] => X-Download-Options: noopen
[9] => X-Frame-Options: SAMEORIGIN
[10] => X-XSS-Protection: 1; mode=block
[11] => Content-Length: 77
[12] => Connection: keep-alive
)
在 Delphi 5 TidHTTP 请求/响应标头下方(不起作用):
Array
(
[0] => POST /graphql HTTP/1.1
[1] => Host: joy.classapp.co
[2] => User-Agent: PHP Curl/1.6 ( https://github.com/php-mod/curl)
[3] => Accept: */*
[4] => Content-Length: 407
[5] => Content-Type: application/x-www-form-urlencoded
)
Array
(
[0] => HTTP/1.1 400 Bad Request
[1] => Access-Control-Allow-Origin: *
[2] => Content-Type: application/json; charset=utf-8
[3] => Date: Mon, 02 Apr 2018 14:47:53 GMT
[4] => ETag: W/"1f6-RtlkHyZy4MNsaj0EjU9LCzebnSs"
[5] => Server: nginx/1.12.1
[6] => X-Content-Type-Options: nosniff
[7] => X-DNS-Prefetch-Control: off
[8] => X-Download-Options: noopen
[9] => X-Frame-Options: SAMEORIGIN
[10] => X-XSS-Protection: 1; mode=block
[11] => Content-Length: 502
[12] => Connection: keep-alive
)
我尝试更改 Content-Type em Curl Class(我正在使用 Curl/Curl 库)以使 POST 到 GraphQL API,但不成功。
我不知道为什么它在浏览器/cURL 中完美运行,而不是在 Delphi 5 中。 问题出在我的 PHP API 或 Delphi 5 TidHTTP 组件中?还是两者兼有?
编辑:使用 GET 和 POST http 动词尝试了 Delphi 5 和 Delphi 2006 以及 Indy v10.1.5。同样的错误。
感谢关注。
【问题讨论】:
-
请显示不适合您的实际 Delphi 代码。 Delphi 5 非常老旧,您使用的是 Delphi 5 附带的 Indy 版本,还是使用最新的现代版本?
-
@RemyLebeau 使用 GET 和 POST http 动词尝试了 Delphi 5 和 Delphi 2006 以及 Indy v10.1.5。同样的错误。我用 Delphi 代码编辑了我的帖子。
-
为什么一开始就使用这些过时的版本? Delphi 5 已经快 20 岁了,而 Indy 10.1.5 也差不多这么老了。当前的 Indy 版本是 10.6.2。在过去十年中,
TIdHTTP发生了许多更改和修复。 -
另外,您遇到的失败是在 POST 请求上,但您的 Delphi 代码正在发送 GET 请求。您没有显示 POST 正文的内容,或接收 GET 然后生成 POST 的 PHP 代码。所以有几个可能的故障点,但您没有提供足够的诊断数据来确定哪一个实际发生故障。