Base on Fraser answer and How can I get my external IP address in a shell script? question
Details
- Swift 5.3
- Version 12.4 (12D4e)
- Alamofire 5
Full Sample
NetworkService.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
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
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)
}
}
Screenshots
