How to Use Urlsession with Proxy in Swift 3

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



Leave a reply



Submit