http - 在 Indy POST 之后访问 JSON 数据
问题描述
我很想知道如何访问对 Indy POST 请求的响应。我将数据作为 JSON 或参数字符串发布。我使用 JSON 时的代码如下。
params := TStringList.Create;
try
params.Text :=
'{'
+ format ('"client_secret":"%s",', [FilesFrm.ClientSecret])
+ format ('"client_id":"%s",', [FilesFrm.ClientId])
+ '"grant_type":"authorization_code",'
+ '"redirect_uri":"http://localhost:8080",'
+ format ('"code":"%s"', [fCode])
+ '}';
idLogFile1.Active := true;
// Make sure it uses HTTP 1.1, not 1.0
IdHTTP1.HTTPOptions := IdHTTP1.HTTPOptions + [hoKeepOrigProtocol];
IdHTTP1.Request.ContentType := 'application/json';
IdHttp1.Request.Accept := 'application/vnd.hmrc.1.0+json';
try
result := IdHTTP1.Post (
'https://test-api.service.hmrc.gov.uk/oauth/token',
params);
except
on E: Exception do
memo1.lines.add (E.ClassName + ': ' + E.message);
end;
memo1.Lines.add (result);
memo1.Lines.add (idHTTP1.ResponseText);
finally
params.free;
end;
打印出 result 和 RepsonseText 的结果就是
EIdHTTPProtocolException: HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
但是,因为我在 TidHTTP 上附加了一个 TidLogFile 组件,所以我可以看到实际到达的内容,如下所示。
Recv 2/1/2019 7:56:07 AM: HTTP/1.1 400 Bad Request<EOL>
Content-Type: application/json<EOL>
Content-Length: 72<EOL>
Cache-Control: no-cache,no-store,etc, etc...
; Secure; HTTPOnly<EOL><EOL>
{"error":"invalid_request","error_description":"grant_type is required"}
除了 grant_type 似乎在原始请求数据中这一事实之外,我希望能够在最后访问 JSON 响应,因为“grant_type_is_required”比“Bad request”更有帮助,但我找不到它在哪里是。
我随后找到了包含值 72 的 Response.ContentLength 和 Response.ContentStream,它理论上应该包含 72 个字节的数据,但是当我尝试提取数据时会产生访问冲突。
len := idHTTP1.Response.ContentLength;
memo1.Lines.Add(format ('Length = %d', [len]));
if assigned (idHTTP1.Response.ContentStream) then
begin
//idHTTP1.Response.ContentStream.Position := 0;
result := ReadStringFromStream (idHTTP1.Response.ContentStream, len);
end;
memo1.lines.add (result);
解决方案
除了技术上正确的 mjn42 的答案之外,它的属性中TIdHTTP
还具有可选hoNoProtocolErrorException
和hoWantProtocolErrorContent
标志HTTPOptions
,您可以启用它们来避免EIdHTTPProtocolException
被引发并result
分别用错误数据填充变量:
params := TStringStream.Create(
'{'
+ format ('"client_secret":"%s",', [FilesFrm.ClientSecret])
+ format ('"client_id":"%s",', [FilesFrm.ClientId])
+ '"grant_type":"authorization_code",'
+ '"redirect_uri":"http://localhost:8080",'
+ format ('"code":"%s"', [fCode])
+ '}',
TEncoding.UTF8);
try
IdLogFile1.Active := true;
// Make sure it uses HTTP 1.1, not 1.0,
// and disable EIdHTTPProtocolException on errors
IdHTTP1.ProtocolVersion := pv1_1;
IdHTTP1.HTTPOptions := IdHTTP1.HTTPOptions + [hoKeepOrigProtocol, hoNoProtocolErrorException, hoWantProtocolErrorContent];
IdHTTP1.Request.ContentType := 'application/json';
IdHTTP1.Request.Accept := 'application/vnd.hmrc.1.0+json';
try
result := IdHTTP1.Post('https://test-api.service.hmrc.gov.uk/oauth/token', params);
except
on E: Exception do begin
Memo1.Lines.Add(E.ClassName + ': ' + E.message);
raise;
end;
end;
Memo1.Lines.Add(result);
finally
params.Free;
end;
推荐阅读
- python - 一些 Tkinter create_line 命令不绘制垂直线,但其他命令
- scikit-learn - 在 scikit-learn 中使用 GridSearchCV 会导致 CalibratedClassifierCV 出现错误。GridSearchCV 对象没有属性 'best_params_
- hive - Apache Beam SqlTransforms 架构问题
- laravel-5.6 - 在 laravel 上创建第一个数据库表的问题
- laravel - laravel 中的单页
- python - 根据条件更改多维numpy数组值
- node.js - 带有节点 js 的 AWS RDS:错误:在参数中找到意外的键“DeleteProtection”
- angular - Angular 4+ - 如何从输入日期选择器中获取日期
- ios - 访问 Node Express 端点时,URLSession.shared.dataTask 数据始终为空
- javascript - map、filter 与 for 和 forEach 之间的区别以及使用 map 和 filter 优于 For 和 forEach 循环的优势是什么?