最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - Authenticate HTTP proxy for request - Stack Overflow

programmeradmin0浏览0评论

I'm simply trying to use a proxy to route a http request in Swift to measure the average round trip time of a list of proxies. I've went through multiple Stack Overflow threads on this topic but they are all super old / outdated.

format: host:port:username:password

Update

  • After fixing the position of group.leave(), and adding the info.plist item as suggested in the comments, I was prompted with the following menu. I closed this menu inside my app and tried the function below again and it worked without giving me the menu a second time. However even though the function works without throwing any errors, it does NOT use the proxies to route the request.

Why does the request work (throws no errors) but does not use the proxies? I'm assuming it's because the password isn't entered in the settings as the alert said. My users will want to test proxy speeds for many different Hosts/Ports, it doesn't make sense to enter the password in settings every time. How can I fix this issue?

func averageProxyGroupSpeed(proxies: [String], completion: @escaping (Int, String) -> Void) {
    let numProxies = proxies.count
    if numProxies == 0 {
        completion(0, "No proxies")
        return
    }

    var totalTime: Int64 = 0
    var successCount = 0
    let group = DispatchGroup()
    let queue = DispatchQueue(label: "proxyQueue", attributes: .concurrent)
    let lock = NSLock()

    let shuffledProxies = proxies.shuffled()
    let selectedProxies = Array(shuffledProxies.prefix(25))

    for proxy in selectedProxies {
        group.enter()
        queue.async {
            let proxyDetails = proxy.split(separator: ":").map(String.init)
            guard proxyDetails.count == 4,
                  let port = Int(proxyDetails[1]),
                  let url = URL(string: ";) else {
                completion(0, "Invalid proxy format")
                group.leave()
                return
            }

            var request = URLRequest(url: url)
            request.timeoutInterval = 15

            let configuration = URLSessionConfiguration.default
            configuration.connectionProxyDictionary = [
                AnyHashable("HTTPEnable"): true,
                AnyHashable("HTTPProxy"): proxyDetails[0],
                AnyHashable("HTTPPort"): port,
                AnyHashable("HTTPSEnable"): false,
                AnyHashable("HTTPUser"): proxyDetails[2],
                AnyHashable("HTTPPassword"): proxyDetails[3]
            ]

            let session = URLSession(configuration: configuration)
            let start = Date()

            let task = session.dataTask(with: request) { _, _, error in
                defer { group.leave() }
                
                if let error = error {
                    print("Error: \(error.localizedDescription)")
                } else {
                    let duration = Date().timeIntervalSince(start) * 1000

                    lock.lock()
                    totalTime += Int64(duration)
                    successCount += 1
                    lock.unlock()
                }
            }
            task.resume()
        }
    }

    group.notify(queue: DispatchQueue.main) {
        if successCount == 0 {
            completion(0, "Proxies Failed")
        } else {
            let averageTime = Int(Double(totalTime) / Double(successCount))
            completion(averageTime, "")
        }
    }
}

Update - Using Delegate

  • Same auth menu pops up
class ProxySessionDelegate: NSObject, URLSessionDelegate {
    let username: String
    let password: String

    init(username: String, password: String) {
        self.username = username
        self.password = password
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic {
            let credential = URLCredential(user: self.username, password: self.password, persistence: .forSession)
            completionHandler(.useCredential, credential)
        } else {
            completionHandler(.performDefaultHandling, nil)
        }
    }
}

func averageProxyGroupSpeed(proxies: [String], completion: @escaping (Int, String) -> Void) {
    let numProxies = proxies.count
    if numProxies == 0 {
        completion(0, "No proxies")
        return
    }

    var totalTime: Int64 = 0
    var successCount = 0
    let group = DispatchGroup()
    let queue = DispatchQueue(label: "proxyQueue", attributes: .concurrent)
    let lock = NSLock()

    let shuffledProxies = proxies.shuffled()
    let selectedProxies = Array(shuffledProxies.prefix(25))

    for proxy in selectedProxies {
        group.enter()
        queue.async {
            let proxyDetails = proxy.split(separator: ":").map(String.init)
            guard proxyDetails.count == 4,
                  let port = Int(proxyDetails[1]),
                  let url = URL(string: ";) else {
                completion(0, "Invalid proxy format")
                group.leave()
                return
            }

            var request = URLRequest(url: url)
            request.timeoutInterval = 15

            let configuration = URLSessionConfiguration.default
            configuration.connectionProxyDictionary = [
                AnyHashable("HTTPEnable"): true,
                AnyHashable("HTTPProxy"): proxyDetails[0],
                AnyHashable("HTTPPort"): port,
                AnyHashable("HTTPSEnable"): false,
                AnyHashable("HTTPUser"): proxyDetails[2],
                AnyHashable("HTTPPassword"): proxyDetails[3]
            ]

            let delegate = ProxySessionDelegate(username: proxyDetails[2], password: proxyDetails[3])
            let session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
            let start = Date()

            let task = session.dataTask(with: request) { _, _, error in
                defer { group.leave() }
                
                if let error = error {
                    print("Error: \(error.localizedDescription)")
                } else {
                    let duration = Date().timeIntervalSince(start) * 1000

                    lock.lock()
                    totalTime += Int64(duration)
                    successCount += 1
                    lock.unlock()
                }
            }
            task.resume()
        }
    }

    group.notify(queue: DispatchQueue.main) {
        if successCount == 0 {
            completion(0, "Proxies Failed")
        } else {
            let averageTime = Int(Double(totalTime) / Double(successCount))
            completion(averageTime, "")
        }
    }
}
发布评论

评论列表(0)

  1. 暂无评论