如何使用请求正文调用 API 端点?

How to call an API endpoint with a request body?

我在 Spring 中构建了一个 REST API,目前运行良好。我现在想在我的请求中添加一个包含数据的正文。我的 REST API 端点,它等待请求中的正文数据,如下所示。

@RestController
public class TestController {

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

我试过通过命令行调用端点,如下所示。

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

结果如下,证明 REST API 工作正常。

Hello John Doe

反正我没能在 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;

有人知道我怎样才能做到这一点吗?我非常感谢任何形式的帮助,sheers!


我尝试过以多种不同的方式调用端点,如下所示。

// see above...

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

RESTRequest.Execute;

遗憾的是,这会导致以下错误。

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

我天真的做法是:

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

这将生成一个普通的字符串主体。如果你真的需要一个 JSON body 你可以写

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

但由于我不熟悉 Spring 我不确定这是否适合这里。

更新: 将服务器更改为接受 JSON 对象后,第二种方法似乎更好。在那种情况下,您甚至可以使用类似的 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;
  

我已将方法从 GET 更改为 POST,因为我只会向 REST API 发送 POST 请求。不幸的是,这解决了我最初的问题,即使我不知道到底为什么......无论如何这里是一个快速演练。

首先,您必须创建一个 class,稍后 Spring 将使用它来使用 JSON 中的给定数据从中创建一个实例。请注意,此步骤是可选的,但非常推荐。

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

更新后的端点如下所示。

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

参考 @Uwe Raabe's 答案,我在 Delphi 中调用 REST API 端点,如下所示。请注意,我在正文数据周围添加了典型的 JSON 语法,这是必要的,因为没有它 Spring 无法创建数据的 class。

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