8

如何在 Vapor 3 中使用HTTPRequeststruct 发送 API 请求?

我尝试了以下代码的变体..

var headers: HTTPHeaders = .init()
let body = HTTPBody(string: a)            
let httpReq = HTTPRequest(
    method: .POST,
    url: URL(string: "/post")!,
    headers: headers,
    body: body)

let httpRes: EventLoopFuture<HTTPResponse> = HTTPClient.connect(hostname: "httpbin.org", on: req).map(to: HTTPResponse.self) { client in
    return client.send(httpReq)
}

编译错误Cannot convert value of type '(HTTPClient) -> EventLoopFuture<HTTPResponse>' to expected argument type '(HTTPClient) -> _'

我已经尝试过其他有效的代码变体。

Vapor 3 Beta 示例端点请求

let client = try req.make(Client.self)

let response: Future<Response> = client.get("http://example.vapor.codes/json")

我读了又读:

4

2 回答 2

7

你的问题是.map(to: HTTPResponse.self)。Map 需要定期将其结果转换为新结果,就像您将map数组一样。但是,您的 map-closure 的结果会返回一个EventLoopFuture<HTTPResponse>. 这会导致您的map函数返回一个EventLoopFuture<EventLoopFuture<HTTPResponse>>.

为避免这种复杂性,请使用flatMap.

var headers: HTTPHeaders = .init()
let body = HTTPBody(string: a)            
let httpReq = HTTPRequest(
    method: .POST,
    url: URL(string: "/post")!,
    headers: headers,
    body: body)

let client = HTTPClient.connect(hostname: "httpbin.org", on: req)

let httpRes = client.flatMap(to: HTTPResponse.self) { client in
    return client.send(httpReq)
}

编辑: 如果你想使用内容 API,你可以这样做:

let data = httpRes.flatMap(to: ExampleData.self) { httpResponse in
    let response = Response(http: httpResponse, using: req)
    return try response.content.decode(ExampleData.self)
}
于 2019-03-19T16:45:46.710 回答
2

HTTPClient.connect返回Future<HTTPClient>,它映射到 aFuture<HTTPResponse>而不是 a EventLoopFuture<HTTPResponse>

如果您期望一次性HTTPResponse使用HttpClient.send而不是HTTPClient.connect.

如果您期望多个HTTPResponses 那么.map(to: HTTPResponse.self)必须更改为正确映射到EventLoopFuture<HTTPResponse>

于 2019-03-19T16:44:16.153 回答