PingServer.swift 2.1 KB

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