IdHTTP如何发送x-www-form-urlencoded正文

时间:2019-12-10 11:23:46

标签: delphi http-post ebay-api idhttp x-www-form-urlencoded

我已经在PostMan中测试了POST函数,以使用以下人体参数执行POST函数:

enter image description here

enter image description here

以下是此功能的eBay文档:

  HTTP method:   POST
  URL (Sandbox): https://api.sandbox.ebay.com/identity/v1/oauth2/token

  HTTP headers:
    Content-Type = application/x-www-form-urlencoded
    Authorization = Basic <B64-encoded-oauth-credentials>

  Request body:
    grant_type=authorization_code
    code=<authorization-code-value>
    redirect_uri=<RuName-value>

我的第一次尝试如下:

function udxEBayExchangeAuthCodeForUserToken(AAuthCode: String; AIsProduction: Boolean): String;
var
  xRequestBody: TStringStream;
begin
  with objHTTP.Request do begin
    CustomHeaders.Clear;
    ContentType := 'application/x-www-form-urlencoded';
    CustomHeaders.Values['Authorization'] := 'Basic ' + 'V2VpbmluZ0MtV2VpbmluZ0M';
  end;

  xRequestBody := TStringStream.Create('grant_type=' + 'authorization_code' + ','
                                     + 'code=' + 'v%5E1.1%23i%5E1%23f%5E0%23r%5E1%23I%5E3%23p%5E3' + ','
                                     + 'redirect_uri=' + 'myredirecturlnameinsandbox',
                                        TEncoding.UTF8);

  try
    try
      Result := objHTTP.Post('https://api.sandbox.ebay.com/identity/v1/oauth2/token', xRequestBody);
    except
      on E: Exception do
        ShowMessage('Error on request: ' + #13#10 + e.Message);
    end;
  finally
    xRequestBody.Free;
  end;
end;

第二次尝试使用下面的Body代码

  xRequestBody := TStringStream.Create('grant_type=' + 'authorization_code' + '&'
                                     + 'code=' + AAuthCode + '&'
                                     + 'redirect_uri=' + gsRuName,
                                        TEncoding.UTF8);

两次尝试都会发出HTTP / 1.1 400错误请求。

我已经在Stack Overflow中进行了一些搜索,这是最接近的问题。唯一不同的部分是POST正文。

IdHTTP how to send raw body

任何人都可以告诉我分配POST正文部分的正确方法是什么? 谢谢。

3 个答案:

答案 0 :(得分:1)

通过application/x-www-form-urlencoded发送TIdHTTP请求的首选方法是使用重载的TIdHTTP.Post()方法,该方法以TStrings作为输入。您没有以正确的TStringStream格式发送application/x-www-form-urlencoded数据。

您不需要使用TIdHTTP.Request.CustomHeaders属性来设置Basic授权。 TIdHTTP具有对Basic的内置支持,只需根据需要使用TIdHTTP.Request.UserNameTIdHTTP.Request.Password属性,并将TIdHTTP.Request.BasicAuthentication属性设置为true。

尝试以下方法:

function udxEBayExchangeAuthCodeForUserToken(AAuthCode: String; AIsProduction: Boolean): String;
var
  xRequestBody: TStringList;
begin
  with objHTTP.Request do
  begin
    Clear;
    ContentType := 'application/x-www-form-urlencoded';
    BasicAuthentication := True;
    UserName := ...;
    Password := ...;
  end;

  xRequestBody := TStringList.Create;
  try
    xRequestBody.Add('grant_type=' + 'authorization_code');
    xRequestBody.Add('code=' + AAuthCode);
    xRequestBody.Add('redirect_uri=' + 'myredirecturlnameinsandbox');

    try
      Result := objHTTP.Post('https://api.sandbox.ebay.com/identity/v1/oauth2/token', xRequestBody);
    except
      on E: Exception do
        ShowMessage('Error on request: ' + #13#10 + e.Message);
    end;
  finally
    xRequestBody.Free;
  end;
end;

如果您要发送自己的TStringStream,请尝试以下方法:

function udxEBayExchangeAuthCodeForUserToken(AAuthCode: String; AIsProduction: Boolean): String;
var
  xRequestBody: TStringStream;
begin
  with objHTTP.Request do
  begin
    Clear;
    ContentType := 'application/x-www-form-urlencoded';
    BasicAuthentication := True;
    UserName := ...;
    Password := ...;
  end;

  xRequestBody := TStringStream.Create('grant_type=' + 'authorization_code' + '&'
                                     + 'code=' + TIdURI.ParamsEncode(AAuthCode){'v%5E1.1%23i%5E1%23f%5E0%23r%5E1%23I%5E3%23p%5E3'} + '&'
                                     + 'redirect_uri=' + 'myredirecturlnameinsandbox',
                                        TEncoding.UTF8);
  try
    try
      xRequestBody.Position := 0;

      Result := objHTTP.Post('https://api.sandbox.ebay.com/identity/v1/oauth2/token', xRequestBody);
    except
      on E: Exception do
        ShowMessage('Error on request: ' + #13#10 + e.Message);
    end;
  finally
    xRequestBody.Free;
  end;
end;

答案 1 :(得分:0)

这个问题让我感到困扰,但是答案并不太有效。后来,我使用数据包捕获来查看实际发送的内容。对于有同样问题的朋友。

function TFormMain.init_web_account(): Boolean;
var
  strTmp: Ansistring;
  PostStringData: TstringStream;
  idhttp1: Tidhttp;
  json, json_array1: TQjson;
  itype_version: integer;
  ifunction_version: integer;
  s: string;
  url: ansistring;
  idMultiPartFormDataStream:TIdMultiPartFormDataStream;
begin
  try
    result := False;
    idhttp1 := TIdHTTP.Create();
    PostStringData := TStringStream.Create;



    //init_string  http://x.x.x.x:8000/user/key?ke1=v1&k2=v2
    strTmp := //
      'strdogsoftid=' + edtDogNumber.Text + //
      '&chipid=' + '' + //
      '&status=' + '0' +  //
      '&reg_user_name=' + edtRegName.Text + //
      '&reg_init_date=' + formatdatetime('yyyy-mm-dd', dtpRegCodeGenDate.Date) + //
      '&lease_expiration=' + formatdatetime('yyyy-mm-dd', dtp_lease_expiration.Date) + //
      '&renew_last_date=' + '' + //
      '&mobile=' + '' + //
      '&weixin=' + '' + //
      '&memo=' + '' + //
      '&function_version=' + IntToStr(rgVersion.ItemIndex) + //
      '&type_version=' + IntToStr(itype_version); //

    url := 'http://x.x.x.x:8000/user/' + edtDogNumber.Text;
    PostStringData.Clear;
    PostStringData.WriteString(strTmp);


    try

      idhttp1.Request.ContentType := 'application/x-www-form-urlencoded';



      s := idhttp1.Post(url, PostStringData); 
      result := True;


    except
      on E: Exception do
      begin
        showmessage(s);
        result := False; 
        exit;
      end;

    end;
  finally
    PostStringData.Free;
    idhttp1.Free;

  end;
end;

答案 2 :(得分:0)

如果您使用 TNetHTTPClient,您可以使用“System.Net.Mime”单元通过 HTTP Post 管理多部分表单数据并管理请求。

我使用 Delphi 10.4.2