Home > front end >  How to call an API endpoint with a request body in Delphi?
How to call an API endpoint with a request body in Delphi?

Time:12-08

I've build a REST API in Spring, which is working well so far. I now want to add a body with data to my request. My REST API endpoint, which awaits the body data in a request looks like the following.

@RestController
public class TestController {

    @GetMapping("/test")
    public String Test(@RequestBody(required=true) String fullName) {
         return "Hello "   fullName;
    }
}

I've tried to call the endpoint via command line, like down below.

curl -X GET -H "Content-type: application/json" -d "John Doe" "http://localhost:8080/test"

This results the following and proves that the REST API is working fine.

Hello John Doe

Anyways I couldn't get it done in Delphi.

procedure TForm1.Button1Click(Sender: TObject);
var
    RESTClient : TRESTClient;
    RESTRequest : TRESTRequest;
    RESTResponse : TRESTResponse;
begin
    RESTClient := TRESTClient.Create(nil);
    RESTClient.BaseURL := 'http://localhost:8080/test';

    RESTResponse := TRESTResponse.Create(nil);

    RESTRequest := TRESTRequest.Create(nil);
    RESTRequest.Client := RESTClient;
    RESTRequest.Response := RESTResponse;
    RESTRequest.Execute;

    if RESTResponse.Status.Success then
    begin
        ShowMessage(RESTResponse.Content);
    end;
end;

Does anybody knows how I can achieve this? I highly appreciate any kind of help, sheers!


I've tried to call the endpoint in many different variations, one shown below.

// see above...

RESTRequest.ClearBody;
RESTRequest.Params.AddHeader('Content-Type', 'application/json');
RESTRequest.Body.Add('{"fullname": "John Doe"}');

RESTRequest.Execute;

Sadly, this results in the following error.

DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Invalid mime type "application%2Fjson": does not contain '/']

CodePudding user response:

My naive approach would be:

RESTRequest.ClearBody;
RESTRequest.AddBody('John Doe');
RESTRequest.Execute;

That will make a plain string body. If you actually need a JSON body you can write

RESTRequest.AddBody('{"fullname": "John Doe"}', TRESTContentType.ctAPPLICATION_JSON);

but as I am not familiar with Spring I am unsure if that fits here.

Update: After you changed your server to accept JSON objects the second approach seems to be the better one. In that case you can even make use of a similar Delphi class.

type
  TPerson = class
  private
    FFirstname: string;
    FLastname: string;
  public
    property Firstname: string read FFirstname write FFirstname;
    property Lastname: string read FLastname write FLastname;
  end;


    person := TPerson.Create;
    try
      person.Firstname := 'John';
      person.Lastname := 'Doe';
      RESTRequest.AddBody<TPerson>(person);
    finally
      person.Free;
    end;
  

CodePudding user response:

I've changed the method from GET to POST, since I will only do POST requests to the REST API. Unfortunately this solved my initial problem, even if I don't know exactly why... Anyways here a quick walkthrough.

Firstly, you have to create a class, which is later be used by Spring to create a instance from it with the given data in the JSON. Note that this step is optional, but very recommended.

public class Person {
    private String firstname;
    private String lastname;

    public Person (String firstname, String lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
    }

    public String getFirstname() {
        return firstname;
    }
    
    public String getLastname() {
        return lastname;
    }
}

The updated endpoint looks like the following.

@PostMapping(
    value = "/test",
    consumes = {MediaType.APPLICATION_JSON_VALUE} // awaits JSON
)
public String Test(@RequestBody Person person) {
    return person.getFirstname()); // will return John
}

Refering to @Uwe Raabe's answer, I am calling the REST API endpoint in Delphi like down below. Note that I've added the typical JSON syntax around the body data, which is necessary due the fact that Spring can't create a class of the data without it.

// ...
RESTRequest.ClearBody;
RESTRequest.AddBody('{"firstname": "John", "lastname": "Doe"}', ctAPPLICATION_JSON);
RESTRequest.Execute;
  • Related