Search code examples
delphihttp-postebay-apiidhttpx-www-form-urlencoded

IdHTTP how to send x-www-form-urlencoded body


I have tested POST function in PostMan to do POST function with body parameters as below:

enter image description here

enter image description here

Here is eBay's document for this function:

  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>

My first attempt was as follow:

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;

Second attempt tried with below code for Body

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

Both attempts give HTTP/1.1 400 Bad Request.

I have done some searching in Stack Overflow, and this is the closest question. The only different part is body of POST.

IdHTTP how to send raw body

Can anyone please advise me what is correct way to assign POST body part? Thanks.


Solution

  • The preferred way to send an application/x-www-form-urlencoded request with TIdHTTP is to use the overloaded TIdHTTP.Post() method that takes a TStrings as input. You are not sending your TStringStream data in the proper application/x-www-form-urlencoded format.

    You don't need to use the TIdHTTP.Request.CustomHeaders property to setup Basic authorization. TIdHTTP has built-in support for Basic, simply use the TIdHTTP.Request.UserName and TIdHTTP.Request.Password properties as needed, and set the TIdHTTP.Request.BasicAuthentication property to true.

    Try this instead:

    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;
    

    If you want to send your own TStringStream, try this instead:

    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;