PingServer.swift 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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. // Server
  10. extension HttpServer {
  11. class func pingServer() -> HttpServer {
  12. let server = HttpServer()
  13. server.GET["/ping"] = { request in
  14. return HttpResponse.ok(.text("pong!"))
  15. }
  16. return server
  17. }
  18. }
  19. let defaultLocalhost = URL(string:"http://localhost:8080")!
  20. // Client
  21. extension URLSession {
  22. func pingTask(
  23. hostURL: URL = defaultLocalhost,
  24. completionHandler handler: @escaping (Data?, URLResponse?, Error?) -> Void
  25. ) -> URLSessionDataTask {
  26. return self.dataTask(with: hostURL.appendingPathComponent("/ping"), completionHandler: handler)
  27. }
  28. func retryPing(
  29. hostURL: URL = defaultLocalhost,
  30. timeout: Double = 2.0
  31. ) -> Bool {
  32. let semaphore = DispatchSemaphore(value: 0)
  33. self.signalIfPongReceived(semaphore, hostURL: hostURL)
  34. let timeoutDate = NSDate().addingTimeInterval(timeout)
  35. var timedOut = false
  36. while semaphore.wait(timeout: DispatchTime.now()) != DispatchTimeoutResult.timedOut {
  37. if NSDate().laterDate(timeoutDate as Date) != timeoutDate as Date {
  38. timedOut = true
  39. break
  40. }
  41. RunLoop.current.run(
  42. mode: RunLoopMode.commonModes,
  43. before: NSDate.distantFuture
  44. )
  45. }
  46. return timedOut
  47. }
  48. func signalIfPongReceived(_ semaphore: DispatchSemaphore, hostURL: URL) {
  49. pingTask(hostURL: hostURL) { data, response, error in
  50. if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
  51. semaphore.signal()
  52. } else {
  53. self.signalIfPongReceived(semaphore, hostURL: hostURL)
  54. }
  55. }.resume()
  56. }
  57. }