Vapor 3 - send a HTTPRequest

喜夏-厌秋 提交于 2020-01-02 02:41:14

问题


How do you send an API request in Vapor 3 with the HTTPRequest struct?

I tried variations of the following code..

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

The compile error Cannot convert value of type '(HTTPClient) -> EventLoopFuture<HTTPResponse>' to expected argument type '(HTTPClient) -> _'

I have tried other variations of code that worked.

Vapor 3 Beta Example Endpoint Request

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

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

I read and re-read:

  • https://api.vapor.codes/http/latest/HTTP/Structs/HTTPRequest.html
  • https://api.vapor.codes/http/latest/HTTP/Classes/HTTPClient.html
  • https://docs.vapor.codes/3.0/http/client/

回答1:


Your problem is .map(to: HTTPResponse.self). Map needs to transform its result into a new result regularly, like you would map an array. However, the result of your map-closure returns an EventLoopFuture<HTTPResponse>. This results in your map function returning an EventLoopFuture<EventLoopFuture<HTTPResponse>>.

To avoid this complexity, use 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)
}

EDIT: If you want to use the Content APIs you can do so like this:

let data = httpRes.flatMap(to: ExampleData.self) { httpResponse in
    let response = Response(http: httpResponse, using: req)
    return try response.content.decode(ExampleData.self)
}



回答2:


HTTPClient.connect returns Future<HTTPClient> and it is mapping to a Future<HTTPResponse> not a EventLoopFuture<HTTPResponse>.

If you're expecting a single HTTPResponse use HttpClient.send instead of HTTPClient.connect.

If you're expecting multiple HTTPResponses then .map(to: HTTPResponse.self) must be changed to properly map to a EventLoopFuture<HTTPResponse>



来源:https://stackoverflow.com/questions/55245418/vapor-3-send-a-httprequest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!