【问题标题】:How to call an API endpoint with a request body?如何使用请求正文调用 API 端点?
【发布时间】:2022-01-13 03:46:25
【问题描述】:

我在 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;

有谁知道我如何做到这一点?我非常感谢任何形式的帮助,纯粹的!


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

// 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 '/']

【问题讨论】:

    标签: json spring rest delphi http-post


    【解决方案1】:

    我的幼稚做法是:

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

    这将生成一个普通的字符串主体。如果您确实需要 JSON 正文,您可以编写

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

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

    更新:在您将服务器更改为接受 JSON 对象后,第二种方法似乎更好。在这种情况下,您甚至可以使用类似的 Delphi 类。

    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;
      
    

    【讨论】:

    • 您的第一种方法会导致以下错误:Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.String com.example.restservice.KernpruefungController.AAG(java.lang.String)]。我无法尝试您的第二种方法,因为 TRESTContentType.ctAPPLICATION_JSON 似乎是一个未定义的标识符。我在这里缺少任何导入吗?
    • 我已经弄清楚我错过了哪个单元。无论如何,它会遇到与另一个相同的错误。
    • 我更新了我的答案,但我仍然不确定。不幸的是,如果不访问 REST 服务器,我无法对其进行测试。
    • 你已经帮了我很多了——我已经弄明白了为什么它不起作用(见我的回答)。也许你知道为什么。顺便说一句,-H 定义了通常包含有关请求的信息的标头,-d 是包含随请求传递的所有数据的正文部分。
    • 我也更喜欢您的初始答案,因为它帮助我找到了解决方案,所以您是否可以将答案更改为初始答案?
    【解决方案2】:

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

    首先,您必须创建一个类,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 无法在没有它的情况下创建数据类。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 2016-04-20
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-28
      相关资源
      最近更新 更多