0

I need to implement in Delphi a requested REST POST satisfying the following conditions:

  • Must include a custom header
  • Payload must be sent as multipart/form-data
  • The URL must contain the parameters

I have written a function like this:

function SendTrans(const   MyAuthToken:  string;
                   const   MyCustomerID: string;
                   const   MyCustomHeader:  string;
                   const   MyTransData:  string;
                   const   MyTransID:  string;
                   out  Answer:  string)
                   : Boolean;
var
  lClient:  TRESTClient;
  lRequest: TRESTRequest;

begin
  lClient := TRESTClient.Create('https://service.example.com/');
  try
    lClient.RaiseExceptionOn500 := True;
    lClient.ContentType := CONTENTTYPE_MULTIPART_FORM_DATA;
    {-}
    lRequest := TRESTRequest.Create(nil);
    try
      lRequest.Client := lClient;
      lRequest.Response := TRESTResponse.Create(lRequest);
      lRequest.AutoCreateParams := True;
      lRequest.Method := rmPOST;
      lRequest.Accept := ctAPPLICATION_JSON;

      lRequest.AddAuthParameter(HTTP_HEADERFIELD_AUTH,
                                'Bearer ' + MyAuthToken,
                                TRESTRequestParameterKind.pkHTTPHEADER,
                                [TRESTRequestParameterOption.poDoNotEncode]);

      lRequest.Resource := 'api/v1/domain/{CustID}/application/{CustID}/data';
      // URL resource segments
      lRequest.AddParameter('CustID', MyCustomerID, pkURLSEGMENT);
      // Custom header
      lRequest.AddParameter('X-extra-ds', MyCustomHeader, pkHTTPHEADER);
      // multipart/form-data
      lRequest.AddParameter('files', MyTransData, pkREQUESTBODY);
      // URL parameters
      lRequest.AddParameter('duplicates', '0', pkQUERY);
      lRequest.AddParameter('reference', MyTransID, pkQUERY);

      try
        lRequest.Execute();
        with  lRequest.Response  do
          if  InRange(StatusCode, 200, 299)  then begin
            Answer := lRequest.Response.Content;
            Result := True
          end { StatusCode = 2xx }
          else begin
            Answer := StatusText;
            Result := False
          end { StatusCode <> 2xx }
      except
        on  eErr : Exception  do begin
          Answer := eErr.ClassName() + ': ' + eErr.Message;
          Result := False
        end  { on Exception }
      end { try-except }
    finally
      lRequest.Free()
    end { try-finally }
  finally
    lClient.Free()
  end { try-finally }
end { SendTrans };

This function returns HTTP error 415: Unsupported Media Type.

I found information that this class will automatically use the multipart/form-data format if there are at least two parameters of type pkREQUESTBODY. As it happens, in this case I only need to upload one element, but for the purpose of the test I have added a second dummy element:

lRequest.AddParameter('X', 'x', pkREQUESTBODY);

After this change, the function returns an HTTP error 400: Bad Request.

The transmitted XML is correct. I verified it with Postman:

enter image description here

My questions are therefore as follows:

  1. Where is the error in this function?
  2. How to implement a REST POST with a payload in multipart/form-data format containing only one element?

I would appreciate any hints and tips. Thank you in advance for them.

I am using Delphi 11.3 Pro (Alexandria).

3
  • Have you tried making the dummy second request parameter also contain valid multipart/form-data format? Perhaps the bad request response is due to the request also transferring invalid body data from the second dummy header. Commented Jul 8 at 9:13
  • After much trial and error, I finally got the code to work. I did this by replacing the TRestClient and TRestRequest components with the THTTPClient component. Of course I also had to rewrite the algorithm a bit. I still don't understand why the above code doesn't work properly. Commented Jul 8 at 16:44
  • The REST components are a bit unreliable especially in older versions of Delphi. We've just experienced an issue where a request that works being compiled on a windows 10 machine doesn't succeed when compiled on an older windows version. Commented Jul 10 at 9:01

0

Browse other questions tagged or ask your own question.