如何使用 swift 进行同步 url 请求 3
How to make synchronous url requests with swift 3
我知道之前有人问过这个问题,我同意大多数答案,这些答案声称最好遵循 Swift 中请求与 URLSession 异步的方式 3. 我有以下场景,其中异步无法使用请求。
使用 Swift 3 并能够在服务器上 运行 swift 我遇到以下问题。
- 服务器接收到来自客户端的请求
- 要处理请求,服务器必须发送 url 请求并等待响应到达。
- 响应到达后,对其进行处理并回复客户端
问题出现在第 2 步,其中 URLSession 使我们能够仅启动异步数据任务。大多数(如果不是全部)服务器端 swift Web 框架不支持异步响应。当请求到达服务器时,所有事情都必须以同步方式完成,最后发送响应。
到目前为止我找到的唯一解决方案是使用 DispatchSemaphore(请参阅最后的示例),我不确定它是否适用于缩放环境。
如有任何帮助或想法,我们将不胜感激。
extension URLSession {
func synchronousDataTaskWithURL(_ url: URL) -> (Data?, URLResponse?, Error?) {
var data: Data?
var response: URLResponse?
var error: Error?
let sem = DispatchSemaphore(value: 0)
let task = self.dataTask(with: url as URL, completionHandler: {
data = [=12=]
response =
error = as Error?
sem.signal()
})
task.resume()
let result = sem.wait(timeout: DispatchTime.distantFuture)
switch result {
case .success:
return (data, response, error)
case .timedOut:
let error = URLSessionError(kind: URLSessionError.ErrorKind.timeout)
return (data, response, error)
}
}
}
我只有 kitura web 框架的经验,这就是我遇到问题的地方。我想所有其他 swift 网络框架都存在类似的问题。
在Vapor中,您可以使用Droplet的客户端进行同步请求。
let res = try drop.client.get("https://httpbin.org")
print(res)
此外,您可以使用 Portal
class 使异步任务同步。
let res = try Portal.open { portal in
asyncClient.get("https://httpbin.org") { res in
portal.close(with: res)
}
}
您的三步问题可以通过使用完成处理程序解决,即回调处理程序 Node.js 约定:
import Foundation
import Kitura
import HeliumLogger
import LoggerAPI
let session = URLSession(configuration: URLSessionConfiguration.default)
Log.logger = HeliumLogger()
let router = Router()
router.get("/test") { req, res, next in
let datatask = session.dataTask(with: URL(string: "http://www.example.com")!) { data, urlResponse, error in
try! res.send(data: data!).end()
}
datatask.resume()
}
Kitura.addHTTPServer(onPort: 3000, with: router)
Kitura.run()
这是您问题解决方案的快速演示,绝不遵循最佳 Swift/Kitura 做法。但是,通过使用完成处理程序,我可以让我的 Kitura 应用程序进行 HTTP 调用以获取 http://www.example.com
处的资源,等待响应,然后将结果发送回我的应用程序的客户端。
Link相关API:https://developer.apple.com/reference/foundation/urlsession/1410330-datatask
我知道之前有人问过这个问题,我同意大多数答案,这些答案声称最好遵循 Swift 中请求与 URLSession 异步的方式 3. 我有以下场景,其中异步无法使用请求。
使用 Swift 3 并能够在服务器上 运行 swift 我遇到以下问题。
- 服务器接收到来自客户端的请求
- 要处理请求,服务器必须发送 url 请求并等待响应到达。
- 响应到达后,对其进行处理并回复客户端
问题出现在第 2 步,其中 URLSession 使我们能够仅启动异步数据任务。大多数(如果不是全部)服务器端 swift Web 框架不支持异步响应。当请求到达服务器时,所有事情都必须以同步方式完成,最后发送响应。
到目前为止我找到的唯一解决方案是使用 DispatchSemaphore(请参阅最后的示例),我不确定它是否适用于缩放环境。
如有任何帮助或想法,我们将不胜感激。
extension URLSession {
func synchronousDataTaskWithURL(_ url: URL) -> (Data?, URLResponse?, Error?) {
var data: Data?
var response: URLResponse?
var error: Error?
let sem = DispatchSemaphore(value: 0)
let task = self.dataTask(with: url as URL, completionHandler: {
data = [=12=]
response =
error = as Error?
sem.signal()
})
task.resume()
let result = sem.wait(timeout: DispatchTime.distantFuture)
switch result {
case .success:
return (data, response, error)
case .timedOut:
let error = URLSessionError(kind: URLSessionError.ErrorKind.timeout)
return (data, response, error)
}
}
}
我只有 kitura web 框架的经验,这就是我遇到问题的地方。我想所有其他 swift 网络框架都存在类似的问题。
在Vapor中,您可以使用Droplet的客户端进行同步请求。
let res = try drop.client.get("https://httpbin.org")
print(res)
此外,您可以使用 Portal
class 使异步任务同步。
let res = try Portal.open { portal in
asyncClient.get("https://httpbin.org") { res in
portal.close(with: res)
}
}
您的三步问题可以通过使用完成处理程序解决,即回调处理程序 Node.js 约定:
import Foundation
import Kitura
import HeliumLogger
import LoggerAPI
let session = URLSession(configuration: URLSessionConfiguration.default)
Log.logger = HeliumLogger()
let router = Router()
router.get("/test") { req, res, next in
let datatask = session.dataTask(with: URL(string: "http://www.example.com")!) { data, urlResponse, error in
try! res.send(data: data!).end()
}
datatask.resume()
}
Kitura.addHTTPServer(onPort: 3000, with: router)
Kitura.run()
这是您问题解决方案的快速演示,绝不遵循最佳 Swift/Kitura 做法。但是,通过使用完成处理程序,我可以让我的 Kitura 应用程序进行 HTTP 调用以获取 http://www.example.com
处的资源,等待响应,然后将结果发送回我的应用程序的客户端。
Link相关API:https://developer.apple.com/reference/foundation/urlsession/1410330-datatask