PingServer.swift 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. //
  2. // PingServer.swift
  3. // Swifter
  4. //
  5. // Created by Brian Gerstle on 8/20/16.
  6. // Copyright © 2016 Damian Kołakowski. All rights reserved.
  7. //
  8. import Foundation
  9. @testable import Swifter
  10. // Server
  11. extension HttpServer {
  12. class func pingServer() -> HttpServer {
  13. let server = HttpServer()
  14. server.GET["/ping"] = { request in
  15. return HttpResponse.ok(.text("pong!"))
  16. }
  17. return server
  18. }
  19. }
  20. let defaultLocalhost = URL(string: "http://localhost:8080")!
  21. // Client
  22. extension URLSession {
  23. func pingTask(
  24. hostURL: URL = defaultLocalhost,
  25. completionHandler handler: @escaping (Data?, URLResponse?, Error?) -> Void
  26. ) -> URLSessionDataTask {
  27. return self.dataTask(with: hostURL.appendingPathComponent("/ping"), completionHandler: handler)
  28. }
  29. func retryPing(
  30. hostURL: URL = defaultLocalhost,
  31. timeout: Double = 2.0
  32. ) -> Bool {
  33. let semaphore = DispatchSemaphore(value: 0)
  34. self.signalIfPongReceived(semaphore, hostURL: hostURL)
  35. let timeoutDate = NSDate().addingTimeInterval(timeout)
  36. var timedOut = false
  37. while semaphore.wait(timeout: DispatchTime.now()) != DispatchTimeoutResult.timedOut {
  38. if NSDate().laterDate(timeoutDate as Date) != timeoutDate as Date {
  39. timedOut = true
  40. break
  41. }
  42. #if swift(>=4.2)
  43. let mode = RunLoop.Mode.common
  44. #else
  45. let mode = RunLoopMode.commonModes
  46. #endif
  47. _ = RunLoop.current.run(
  48. mode: mode,
  49. before: NSDate.distantFuture
  50. )
  51. }
  52. return timedOut
  53. }
  54. func signalIfPongReceived(_ semaphore: DispatchSemaphore, hostURL: URL) {
  55. pingTask(hostURL: hostURL) { _, response, _ in
  56. if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
  57. semaphore.signal()
  58. } else {
  59. self.signalIfPongReceived(semaphore, hostURL: hostURL)
  60. }
  61. }.resume()
  62. }
  63. }