[英]How to use a Proxy Server with Alamofire 4 and Swift 3
Please don't mark as duplicate, I haven't been able to solve my Issue with the existing threads.请不要标记为重复,我无法用现有线程解决我的问题。
I'm trying to use my Proxy for an API request that needs a specified IP.我正在尝试将我的代理用于需要指定 IP 的 API 请求。 To debug my issue, I'm requesting the IP from a webservice.为了调试我的问题,我从网络服务请求 IP。
This is my current code:这是我当前的代码:
import UIKit
import Alamofire
class ViewController: UIViewController {
var requestManager = Alamofire.SessionManager.default
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
var proxyConfiguration = [NSObject: AnyObject]()
proxyConfiguration[kCFNetworkProxiesHTTPProxy] = "http://xxx@eu-west-static-01.quotaguard.com" as AnyObject?
proxyConfiguration[kCFNetworkProxiesHTTPPort] = "9293" as AnyObject?
proxyConfiguration[kCFNetworkProxiesHTTPEnable] = 1 as AnyObject?
let cfg = Alamofire.SessionManager.default.session.configuration
cfg.connectionProxyDictionary = proxyConfiguration
let ip = URL(string: "https://api.ipify.org?format=json")
requestManager = Alamofire.SessionManager(configuration: cfg)
requestManager.request(ip!).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)")
}
}
}
}
The problem: the responsed IP is the same with or without the proxyConfiguration
.问题:无论有没有proxyConfiguration
,响应的 IP 都是相同的。 Any help is very appreciated.非常感谢任何帮助。
PS: physical device used. PS:使用的物理设备。
I think the working (supposed to be deprecated) keys are:我认为工作(应该被弃用)键是:
kCFStreamPropertyHTTPSProxyHost
kCFStreamPropertyHTTPSProxyPort
Could you try this code?你能试试这个代码吗?
import UIKit
import Alamofire
class ViewController: UIViewController {
var requestManager = Alamofire.SessionManager.default
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
var proxyConfiguration = [NSObject: AnyObject]()
proxyConfiguration[kCFNetworkProxiesHTTPProxy] = "eu-west-static-01.quotaguard.com" as AnyObject?
proxyConfiguration[kCFNetworkProxiesHTTPPort] = "9293" as AnyObject?
proxyConfiguration[kCFNetworkProxiesHTTPEnable] = 1 as AnyObject?
proxyConfiguration[kCFStreamPropertyHTTPSProxyHost as String] = "eu-west-static-01.quotaguard.com"
proxyConfiguration[kCFStreamPropertyHTTPSProxyPort as String] = 9293
proxyConfiguration[kCFProxyUsernameKey as String] = xxx
//proxyConfiguration[kCFProxyPasswordKey as String] = "pwd if any"
let cfg = Alamofire.SessionManager.default.session.configuration
cfg.connectionProxyDictionary = proxyConfiguration
let ip = URL(string: "https://api.ipify.org?format=json")
requestManager = Alamofire.SessionManager(configuration: cfg)
requestManager.request(ip!).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)")
}
}
}
}
Also please make sure your proxy server is configured to handle https requests.另外请确保您的代理服务器配置为处理 https 请求。
Note: It might give deprecated
warning for those keys but keys are still working (see https://forums.developer.apple.com/thread/19356#131446 )注意:它可能会为这些键提供deprecated
警告,但键仍在工作(请参阅https://forums.developer.apple.com/thread/19356#131446 )
Note: I posted the same answer here .注意:我在这里发布了相同的答案。 Posting the same here as it was applicable here as well.在此处发布相同的内容,因为它也适用于此处。 Alamofire is using same URLSessionConfiguration
. Alamofire 使用相同的URLSessionConfiguration
。
Based off Manishg's answer I use the following to avoid warnings根据 Manishg 的回答,我使用以下内容来避免警告
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
var proxyConfiguration = [String: AnyObject]()
proxyConfiguration.updateValue(1 as AnyObject, forKey: "HTTPEnable")
proxyConfiguration.updateValue("eu-west-static-01.quotaguard.com" as AnyObject, forKey: "HTTPProxy")
proxyConfiguration.updateValue(9293 as AnyObject, forKey: "HTTPPort")
proxyConfiguration.updateValue(1 as AnyObject, forKey: "HTTPSEnable")
proxyConfiguration.updateValue("eu-west-static-01.quotaguard.com" as AnyObject, forKey: "HTTPSProxy")
proxyConfiguration.updateValue(9293 as AnyObject, forKey: "HTTPSPort")
configuration.connectionProxyDictionary = proxyConfiguration
sharedManager = Alamofire.SessionManager(configuration: configuration)
The https constants have been deprecated and could be removed at anytime. https 常量已被弃用,可以随时删除。 By using the string values, the code might break but it won't crash通过使用字符串值,代码可能会中断但不会崩溃
Base on Fraser answer and How can I get my external IP address in a shell script?基于Fraser 的回答以及如何在 shell 脚本中获取我的外部 IP 地址? question题
NetworkService.swift网络服务.swift
import Foundation
import Alamofire
struct Proxy {
let host: String
let port: Int
}
class NetworkService {
// Pick free some proxies from here https://free-proxy-list.net if current do not work
private let listOfProxies = [
Proxy(host: "67.43.224.131", port: 3128), // Canada
Proxy(host: "167.172.180.40", port: 44129), // Germany
Proxy(host: "185.236.202.205", port: 3128), // Austria
]
private(set) var session: Session!
private var proxy: Proxy?
init () { resetSessionManager() }
func setRandomProxy() {
self.proxy = listOfProxies.randomElement()
resetSessionManager()
}
private
func resetSessionManager() {
let config = Session.default.session.configuration
if let proxy = proxy {
config.connectionProxyDictionary = [
"HTTPEnable": 1,
"HTTPProxy": proxy.host ,
"HTTPPort": proxy.port,
"HTTPSEnable": true,
"HTTPSProxy": proxy.host,
"HTTPSPort": proxy.port
]
} else {
config.connectionProxyDictionary = [:]
}
self.session = Session(configuration: config)
}
func request(url: URLConvertible,
method: Alamofire.HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil,
completion: @escaping (Result<Data, Error>) -> Void) {
let request = session.request(url, method: method,
parameters: parameters,
encoding: encoding,
headers: headers)
request.response { respionse in
if let error = respionse.error {
completion(.failure(error))
} else if let data = respionse.data {
completion(.success(data))
}
}
}
func request<T: Decodable>(url: URLConvertible,
method: Alamofire.HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil,
completion: @escaping (Result<T, Error>) -> Void) {
request(url: url, method: method,
parameters: parameters,
encoding: encoding,
headers: headers) { result in
switch result {
case .failure(let error): completion(.failure(error))
case .success(let data):
do {
let object = try JSONDecoder().decode(T.self, from: data)
completion(.success(object))
} catch let error {
completion(.failure(error))
}
}
}
}
}
GeoIP.swift GeoIP.swift
import Foundation
struct GeoIP: Codable {
let lat: Double
let lon: Double
let zip: String
let query: String
let city: String
let regionName: String
let country: String
let timezone: String
}
extension GeoIP: CustomStringConvertible {
var description: String {
"\(city), \(regionName), \(country), \(zip)\nIP:\(query)\nCoordinates:(\(lat),\(lon))\nTimezone: \(timezone)"
}
}
ViewController.swift视图控制器.swift
class ViewController: UIViewController {
private let networkService = NetworkService()
private weak var button: UIButton!
private weak var activityIndicatorView: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: view.frame)
button.setTitleColor(.blue, for: .normal)
button.setTitle("Pick random proxy and get my ip", for: .normal)
button.addTarget(self, action: #selector(buttonTouchedUpInside(source:)), for: .touchUpInside)
view.addSubview(button)
self.button = button
let activityIndicatorView = UIActivityIndicatorView(frame: view.frame)
view.addSubview(activityIndicatorView)
self.activityIndicatorView = activityIndicatorView
}
@objc func buttonTouchedUpInside(source: UIButton) {
source.isHidden = true
activityIndicatorView.startAnimating()
networkService.setRandomProxy()
showMyGeoIpInfo()
}
}
extension ViewController {
private func showMyGeoIpInfo() {
let group = DispatchGroup()
group.enter()
group.enter()
group.enter()
var httpIP: String?
var httpsIP: String?
var geoIp: GeoIP?
group.notify(queue: .main) { [weak self] in
guard let self = self else { return }
let _httpIP = httpIP ?? "nil"
let _httpsIP = httpsIP ?? "nil"
let geoIpDescription = geoIp?.description ?? "nil"
let message = "HTTP request IP: \(_httpIP)\nHTTPS request IP: \(_httpsIP)\n GeoIP: \(geoIpDescription)"
self.showAlert(title: "GeoIP", message: message)
self.button.isHidden = false
self.activityIndicatorView.stopAnimating()
}
// Get my IP on http request
getSimpleText(from: "http://ipecho.net/plain") { text in
httpIP = text
group.leave()
}
// Get my IP on https request
getSimpleText(from: "https://icanhazip.com") { text in
httpsIP = text
group.leave()
}
// Get my GeoIp info
networkService.request(url: "http://ip-api.com/json/",
encoding: JSONEncoding.default) { (response: Result<GeoIP, Error>) in
defer { group.leave() }
switch response {
case .failure(let error): print("Error: \(error)")
case .success(let value): geoIp = value
}
}
}
private func getSimpleText(from url: String, completion: @escaping (String?) -> Void) {
networkService.request(url: "https://icanhazip.com") { result in
switch result {
case .failure(let error):
print("Error: \(error)")
completion(nil)
case .success(let data):
let text = String(decoding: data, as: UTF8.self).trimmingCharacters(in: .whitespacesAndNewlines)
completion(text)
}
}
}
private func showAlert(title: String?, message: String?) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
present(alertController, animated: true, completion: nil)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.