How to use URLSession with Proxy in Swift 3
I think the working (supposed to be deprecated) keys are:
kCFStreamPropertyHTTPSProxyHost
kCFStreamPropertyHTTPSProxyPort
Could you try this code?
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()
}
Also please make sure your proxy server is configured to handle https requests.
Note: It might give deprecated
warning for those keys but keys are still working (see https://forums.developer.apple.com/thread/19356#131446)
How to programmatically add a proxy to an NSURLSession
It turns out, the dictionary keys you want are the Stream variants, they are the ones that resolve down to "HTTPProxy" and such:
NSString* proxyHost = @"myProxyHost.com";
NSNumber* proxyPort = [NSNumber numberWithInt: 12345];
// Create an NSURLSessionConfiguration that uses the proxy
NSDictionary *proxyDict = @{
@"HTTPEnable" : [NSNumber numberWithInt:1],
(NSString *)kCFStreamPropertyHTTPProxyHost : proxyHost,
(NSString *)kCFStreamPropertyHTTPProxyPort : proxyPort,
@"HTTPSEnable" : [NSNumber numberWithInt:1],
(NSString *)kCFStreamPropertyHTTPSProxyHost : proxyHost,
(NSString *)kCFStreamPropertyHTTPSProxyPort : proxyPort,
};
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
configuration.connectionProxyDictionary = proxyDict;
// Create a NSURLSession with our proxy aware configuration
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// Form the request
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.google.com?2"]];
// Dispatch the request on our custom configured session
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"NSURLSession got the response [%@]", response);
NSLog(@"NSURLSession got the data [%@]", data);
}];
NSLog(@"Lets fire up the task!");
[task resume];
how to authenticate the proxy in urlsession?
URLSessionConfiguration
need additional headers.
let configuration.httpAdditionalHeaders = ["Proxy-Authorization": Request.authorizationHeader(user: "user", password: "password") ]
How to use a Proxy Server with Alamofire 4 and Swift 3
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.
Note: It might give deprecated
warning for those keys but keys are still working (see 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
.
How to set Proxy in web-view swift?
Once you created your custom url protocol handler, register it in using below code so your protocol will have priority over any of the built-in protocols.
import UIKit
import CoreFoundation
class ViewController: UIViewController {
@IBOutlet weak var sWebViewOutlet : UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
setupViewDidLoad()
}
func setupViewDidLoad() {
SpecialProtocol.registerSpecialProtocol()
let url = NSURL(string: "http://www.google.com")
let req = NSURLRequest(URL: url!)
/* if this request will be handled by our special protocol... */
//if ( [SpecialProtocol canInitWithRequest:request] ) {
if SpecialProtocol.canInitWithRequest(req) {
print("SpecialProtocol.canInitWithRequest(req)")
self.sWebViewOutlet.loadRequest(req)
}
else {
print("SpecialProtocol.cantInitWithRequest(req)")
}
}
}
A subclass of NSURLProtocol class that will handle all web protocols such as HTTP, HTTPS, SSL etc. It provides the basic structure for performing protocol-specific loading of URL data.
Below code, solved my problem... I'll appreciate if you post a better solution or answer than mine.
import UIKit
import CoreFoundation
class SpecialProtocol: NSURLProtocol, NSURLSessionDataDelegate, NSURLSessionTaskDelegate {
//var httpMessageRef: CFHTTPMessage;()
var httpMessageRef: CFHTTPMessage?
class func registerSpecialProtocol() {
var inited: Bool = false
if !inited {
NSURLProtocol.registerClass(SpecialProtocol.self)
inited = true
}
}
private var dataTask:NSURLSessionDataTask?
private var urlResponse:NSURLResponse?
private var receivedData:NSMutableData?
class var CustomKey:String {
return "myCustomKey"
}
// MARK: NSURLProtocol
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
if (NSURLProtocol.propertyForKey(SpecialProtocol.CustomKey, inRequest: request) != nil) {
return false
}
return true
}
override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
return request
}
override func startLoading() {
let newRequest = self.request.mutableCopy() as! NSMutableURLRequest
NSURLProtocol.setProperty("true", forKey: SpecialProtocol.CustomKey, inRequest: newRequest)
let defaultConfigObj = customizeEphemeralSessionConfiguration()//NSURLSessionConfiguration.defaultSessionConfiguration()
let defaultSession = NSURLSession(configuration: defaultConfigObj, delegate: self, delegateQueue: nil)
self.dataTask = defaultSession.dataTaskWithRequest(newRequest)
self.dataTask!.resume()
}
func customizeEphemeralSessionConfiguration() -> NSURLSessionConfiguration {
let proxy_server: CFString = "YourProxyServer" // proxy server
let proxy_port: CFNumber = 1234 // your port
let hostKey: NSString = kCFNetworkProxiesHTTPProxy as NSString
let portKey: NSString = kCFNetworkProxiesHTTPPort as NSString
let proxyDict:[String:AnyObject] = [kCFNetworkProxiesHTTPEnable as String: true, hostKey as String:proxy_server, portKey as String: proxy_port]
let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()
config.connectionProxyDictionary = proxyDict as [NSObject : AnyObject]
return config
}
override func stopLoading() {
self.dataTask?.cancel()
self.dataTask = nil
self.receivedData = nil
self.urlResponse = nil
}
// MARK: NSURLSessionDataDelegate
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask,
didReceiveResponse response: NSURLResponse,
completionHandler: (NSURLSessionResponseDisposition) -> Void) {
self.client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
self.urlResponse = response
self.receivedData = NSMutableData()
completionHandler(.Allow)
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.client?.URLProtocol(self, didLoadData: data)
self.receivedData?.appendData(data)
}
// MARK: NSURLSessionTaskDelegate
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if error != nil && error!.code != NSURLErrorCancelled {
self.client?.URLProtocol(self, didFailWithError: error!)
} else {
saveCachedResponse()
self.client?.URLProtocolDidFinishLoading(self)
}
}
// MARK: Private methods
/**
Do whatever with the data here
*/
func saveCachedResponse () {
let timeStamp = NSDate()
let urlString = self.request.URL?.absoluteString
let dataString = NSString(data: self.receivedData!, encoding: NSUTF8StringEncoding) as NSString?
print("TimeStamp:\(timeStamp)\nURL: \(urlString)\n\nDATA:\(dataString)\n\n")
}
}
Related Topics
Adding a Target to a Button Programmatically Throws an Error "Unrecognized Selector Sent to Class"
iOS Swift Flood Fill Algorithm
Coretelephony Esim Functions Not Working on Device
Ksecattrkeytypeec Causing Encryptmessagewithpublickey() to Fail
Saving Array Using Nsuserdefaults Crashes App
Uialertcontroller Visible Only When Viewdidappear Has Finished Its Call
Swift/How to Call Delegate with Popviewcontroller
Create Alert Function in All View Controllers - Swift
Save Uiimage Array in Nsuserdefaults
Operation Went Isfinished=Yes Without Being Started by the Queue It Is In
Pausing Timer When App Is in Background State Swift
Game Exits from Pause State After Resuming It from Background in Swift
Facebook Sdk Login Throws Error in Swift 2 iOS 9
How to Get the Index (String.Index) Value from the Cursor Position of a Uitextview Element in Swift
Allow Users to Send Messages to Multiple Users Simultaneously in a Messaging App
Uiimageview .Scaleaspectfit and Autolayout Not Working Programmatically from Swift