在 Indy POST 之后访问 JSON 数据 [英] Accessing JSON data after Indy POST

查看:29
本文介绍了在 Indy POST 之后访问 JSON 数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力了解如何访问对 Indy POST 请求的响应.我将数据作为 JSON 或 paramstring 发布.我使用JSON时的代码如下.

I am struggling to know how to access the response to an Indy POST request. I post the data either as JSON or paramstring. My code when using JSON is as follows.

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的结果就是

The result of printing out result and RepsonseText is just

EIdHTTPProtocolException: HTTP/1.1 400 Bad Request

HTTP/1.1 400 Bad Request

但是,因为我在TidHTTP上附加了一个TidLogFile组件,所以我可以看到实际到达的内容,如下所示.

However, because I have a TidLogFile component attached to the TidHTTP, I can see what actually arrives, which is the following.

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"比错误请求"更有帮助,但我不能找到它在哪里.

Aside from the fact that grant_type appears to be in the original request data, I would like to be able to access the JSON response at the end, since "grant_type_is_required" is much more helpful than "Bad request", but I cannot find where it is.

我随后找到了 Response.ContentLength,它包含值 72,以及 Response.ContentStream,它理论上应该包含 72 个字节的数据,但是当我尝试提取数据时会产生访问冲突.

I have subsequently found Response.ContentLength, which contains the value 72, and Response.ContentStream, which should in theory contain the 72 bytes of data, but produces access violations when I try to extract the data.

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);

推荐答案

这里有一个 示例 显示了如何访问 HTTP 正文.

Here is an example which shows how the HTTP body can be accessed.

如果您捕获 EIdHTTPProtocolException 异常,则可以访问正文.

The body can be accessed if you catch the EIdHTTPProtocolException exception.

  on E: EIdHTTPProtocolException do
  begin
    WriteLn(E.Message);
    WriteLn(E.ErrorMessage);
  end;

完整的示例代码:

program JSONPostExample;

{$APPTYPE CONSOLE}

uses
  IdHTTP, IdGlobal, SysUtils, Classes;

var
  HTTP: TIdHTTP;
  RequestBody: TStream;
  ResponseBody: string;
begin
  HTTP := TIdHTTP.Create;
  try
    try
      RequestBody := TStringStream.Create('{"日本語":42}',
        TEncoding.UTF8);
      try
        HTTP.Request.Accept := 'application/json';
        HTTP.Request.ContentType := 'application/json';
        ResponseBody := HTTP.Post('https://httpbin.org/post',
          RequestBody);
        WriteLn(ResponseBody);
        WriteLn(HTTP.ResponseText);
      finally
        RequestBody.Free;
      end;
    except
      on E: EIdHTTPProtocolException do
      begin
        WriteLn(E.Message);
        WriteLn(E.ErrorMessage);
      end;
      on E: Exception do
      begin
        WriteLn(E.Message);
      end;
    end;
  finally
    HTTP.Free;
  end;
  ReadLn;
  ReportMemoryLeaksOnShutdown := True;
end.

请注意,您不能将 TStringList 用于 POST 正文.那个版本的 TIdHTTP.Post() 根据 application/x-www-form-urlencoded 媒体类型格式化数据,这不适合 JSON 并且会破坏它.

Note that you must not use a TStringList for the POST body. That version of TIdHTTP.Post() formats the data according to the application/x-www-form-urlencoded media type, which is not appropriate for JSON and will corrupt it.

这篇关于在 Indy POST 之后访问 JSON 数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆