如何在 Swift 3 中使用带有代理的 URLSession

Posted

技术标签:

【中文标题】如何在 Swift 3 中使用带有代理的 URLSession【英文标题】:How to use URLSession with Proxy in Swift 3 【发布时间】:2017-03-06 04:31:45 【问题描述】:

对于 API 请求,我正在尝试使用代理设置 URLSession。出于测试目的,我使用了公共代理和响应 IP 的 API。

func makeRequestViaUrlSessionProxy(_ url: String, completion: @escaping (_ result: String?) -> ()) 

    let request = URLRequest(url: URL(string: url)!)

    let config = URLSessionConfiguration.default
    config.requestCachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
    config.connectionProxyDictionary = [AnyHashable: Any]()
    config.connectionProxyDictionary?[kCFNetworkProxiesHTTPEnable as String] = 1
    config.connectionProxyDictionary?[kCFNetworkProxiesHTTPProxy as String] = "142.54.173.19"
    config.connectionProxyDictionary?[kCFNetworkProxiesHTTPPort as String] = 8888

    let session = URLSession.init(configuration: config, delegate: nil, delegateQueue: OperationQueue.current)

    let task = session.dataTask(with: request) 
        (data: Data?, response: URLResponse?, error: Error?) in
        if error != nil 
            NSLog("Client-side error in request to \(url): \(error)")
            completion(nil)
            return
        

        if data == nil 
            NSLog("Data from request to \(url) is nil")
            completion(nil)
            return
        

        let httpResponse = response as? HTTPURLResponse
        if httpResponse?.statusCode != 200 
            NSLog("Server-side error in request to \(url): \(httpResponse)")
            completion(nil)
            return
        

        let encodingName = response?.textEncodingName != nil ? response?.textEncodingName : "utf-8"
        let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName as CFString!))
        let stringData = String(data: data!, encoding: String.Encoding(rawValue: UInt(encoding)))
        session.invalidateAndCancel()
        completion(stringData)
    
    task.resume()

调用者:

override func viewDidLoad() 
    super.viewDidLoad()
    makeRequestViaUrlSessionProxy("https://api.ipify.org?format=json")  string in
        print(string)
    

似乎config 被完全忽略了,因为即使使用了代理 IP,响应的 IP 也始终是实际设备 IP

非常感谢任何帮助。

编辑:正如用户 hasan83 所建议的,使用“HTTPS 密钥”似乎不是一种选择。

【问题讨论】:

你好,142.54.173.19这个ip是哪个ip地址,路由器还是其他。 ? 【参考方案1】:

我认为有效的(应该被弃用的)键是:

kCFStreamPropertyHTTPSProxyHost
kCFStreamPropertyHTTPSProxyPort

你能试试这个代码吗?

func makeRequestViaUrlSessionProxy(_ url: String, completion: @escaping (_ result: String?) -> ()) 

    let request = URLRequest(url: URL(string: url)!)

    let config = URLSessionConfiguration.default
    config.requestCachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
    config.connectionProxyDictionary = [AnyHashable: Any]()
    config.connectionProxyDictionary?[kCFNetworkProxiesHTTPEnable as String] = 1
    config.connectionProxyDictionary?[kCFNetworkProxiesHTTPProxy as String] = "142.54.173.19"
    config.connectionProxyDictionary?[kCFNetworkProxiesHTTPPort as String] = 8888
    config.connectionProxyDictionary?[kCFStreamPropertyHTTPSProxyHost as String] = "142.54.173.19"
    config.connectionProxyDictionary?[kCFStreamPropertyHTTPSProxyPort as String] = 8888

    let session = URLSession.init(configuration: config, delegate: nil, delegateQueue: OperationQueue.current)

    let task = session.dataTask(with: request) 
        (data: Data?, response: URLResponse?, error: Error?) in
        if error != nil 
            NSLog("Client-side error in request to \(url): \(error)")
            completion(nil)
            return
        

        if data == nil 
            NSLog("Data from request to \(url) is nil")
            completion(nil)
            return
        

        let httpResponse = response as? HTTPURLResponse
        if httpResponse?.statusCode != 200 
            NSLog("Server-side error in request to \(url): \(httpResponse)")
            completion(nil)
            return
        

        let encodingName = response?.textEncodingName != nil ? response?.textEncodingName : "utf-8"
        let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName as CFString!))
        let stringData = String(data: data!, encoding: String.Encoding(rawValue: UInt(encoding)))
        session.invalidateAndCancel()
        completion(stringData)
    
    task.resume()

另外请确保您的代理服务器已配置为处理 https 请求。

注意:它可能会为这些键发出 deprecated 警告,但键仍在工作(请参阅 https://forums.developer.apple.com/thread/19356#131446)

【讨论】:

似乎有效。明天会有更多的测试,但似乎就是这样。 就我目前的研究而言,您的配置也应该在这里工作,所以请随意尝试,如果有效,也在这里回答:***.com/questions/42616908/… 是的,同样的配置应该与 alamofire 会话管理器一起使用,因为它们也使用 URLSessionConfiguration.default 。感谢您的提醒。我会在那里发布答案。 去其他页面时是否可以保留IP地址?当前第一个加载的页面有代理IP,但是当您单击并重定向到其他页面时,它会显示您的原始IP地址。 @RobinCarloCatacutan 您找到问题的答案了吗?我也有兴趣在重定向时保留 IP 地址。【参考方案2】:

我不确定这是否有意义。但是,这里有两组不同的键:

    HTTP HTTPS

代理密钥:

// http proxy keys
kCFNetworkProxiesHTTPEnable
kCFNetworkProxiesHTTPProxy
kCFNetworkProxiesHTTPPort

// https proxy keys
kCFNetworkProxiesHTTPSEnable
kCFNetworkProxiesHTTPSProxy
kCFNetworkProxiesHTTPSPort

【讨论】:

我已经复制/粘贴了您建议的 https 值,但我得到的只是“xy 不可用”。另外,HTTP“S”在 autofil 中不可用 查看添加的屏幕

以上是关于如何在 Swift 3 中使用带有代理的 URLSession的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 3 中添加带有 ConcerrencyType 的 NSManagedObjectContext?

swift 带有哈希表的多播代理

带有 XML 响应和正文的 SOAP 请求 swift 3,Alamofire

如何在 Swift 3 中保存带有顶部图像的相机照片

如何在 swift 3 中的 tableview 单元格中添加带有自定义视图的 collectionView?

在Chrome中,最终使用带有正则表达式的重定向扩展程序,如何将所有facebook.com网址重定向到mbasic.facebook.com URLS