Swift URLSession Redirection Prevention

I need to get the redirect URL, but prevent the redirect in Swift. From other Apple posts and documents, I understand that I have to implement the URLSession(session:, task:, willPerformHTTPRedirection response:, request:, completionHandler:) delegate URLSession(session:, task:, willPerformHTTPRedirection response:, request:, completionHandler:) and return nil through closing completion. But I canโ€™t find examples in quick and donโ€™t know how to do it right. The following code reproduces my problem on the playground: the delegate does not seem to be executing.

 import Foundation import XCPlayground XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true) class MySession: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate { // trying to follow instructions at https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSessionTaskDelegate_protocol/index.html#//apple_ref/occ/intfm/NSURLSessionTaskDelegate/URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler: // to prevent redirection -- DOES NOT SEEM TO GET CALLED func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) { println("in URLSession delegate") // NEVER PRINTS completionHandler(nil) // NO EFFECT } // fetch data from URL with NSURLSession class func getDataFromServerWithSuccess(myURL: String, success: (response: String!) -> Void) { var session = NSURLSession.sharedSession() let loadDataTask = session.dataTaskWithURL(NSURL(string: myURL)!) { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in // OMITTING ERROR CHECKING FOR BREVITY success(response: NSString(data: data!, encoding: NSASCIIStringEncoding) as String) } loadDataTask.resume() } // extract data from redirect class func getRedirectionInfo(url: String) { getDataFromServerWithSuccess(url) {(data) -> Void in if let html = data { if html.rangeOfString("<html><head><title>Object moved</title>", options: .RegularExpressionSearch) != nil { println("success: redirection was prevented") // SHOULD PRINT THIS } else { println("failure: redirection went through") // INSTEAD PRINTS THIS } } } } } MySession.getRedirectionInfo("http://bit.ly/filmenczer") // ex. redirecting link 

Please be careful, I'm new. Thank you in advance for your help!

UPDATE: Thanks a lot thanks to @nate, I got it to work. The basic idea is that in order for the delegate to be called, you need to pass the delegate class to the NSURLSession() initializer, and not use NSURLSession.sharedSession() . Passing nil as the delegate gives the usual behavior (with redirection). Here is the working version of the code:

 import Foundation import XCPlayground XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true) class MySession: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate { // to prevent redirection func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) { completionHandler(nil) } // fetch data from URL with NSURLSession class func getDataFromServerWithSuccess(myURL: String, noRedirect: Bool, success: (response: String!) -> Void) { var myDelegate: MySession? = nil if noRedirect { myDelegate = MySession() } let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: myDelegate, delegateQueue: nil) let loadDataTask = session.dataTaskWithURL(NSURL(string: myURL)!) { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in // OMITTING ERROR CHECKING FOR BREVITY success(response: NSString(data: data!, encoding: NSASCIIStringEncoding) as String) } loadDataTask.resume() } // extract data from redirect class func getRedirectionInfo(url: String) { getDataFromServerWithSuccess(url, noRedirect: true) {(data) -> Void in if let html = data { if html.rangeOfString("<html>\n<head><title>Bitly</title>", options: .RegularExpressionSearch) != nil { println("success: redirection was prevented") } else { println("failure: redirection went through") } } } } } MySession.getRedirectionInfo("http://bit.ly/filmenczer") 
+6
source share
2 answers

You have two things standing in your way with your current implementation.

  • You never set the delegate property in the NSURLSession instance that you use to execute the request. Without the delegate property set, your delegate methods will never be called. Instead of getting NSURLSession.sharedSession() , look at the NSURLSession(configuration:delegate:delegateQueue:) initializer NSURLSession(configuration:delegate:delegateQueue:) . The first and last parameters can be NSURLSessionConfiguration.defaultSessionConfiguration() and nil , respectively, see below for more details on the delegate.

    Note that when using the session.dataTaskWithURL option, which has a completion handler, delegate methods that handle the response and data delivery will be ignored, but authentication and redirection handlers are still used.

  • You will have to reorganize the use of MySession as a delegate a bit, since you use class methods to execute the request. You need an instance to use as a session delegate.

I took a short and incomplete way for the delegate to take the redirect using this alternative code - you will need to reorganize, as in No. 3, to make sure that you can still call your callback:

 class func getDataFromServerWithSuccess(myURL: String, success: (response: String!) -> Void) { let delegate = MySession() var session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: delegate, delegateQueue: nil) let task = session.dataTaskWithURL(NSURL(string: myURL)!) { // ... } task.resume() } 

Hope this helps!

+2
source

Minor adjustments to proposed solutions. This works with Swift 2 in Xcode 7.

 import UIKit import Foundation import XCPlayground XCPSetExecutionShouldContinueIndefinitely(true) class MySession: NSObject, NSURLSessionDelegate { // to prevent redirection func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) { completionHandler(nil) } // fetch data from URL with NSURLSession class func getDataFromServerWithSuccess(myURL: String, noRedirect: Bool, success: (response: String!) -> Void) { var myDelegate: MySession? = nil if noRedirect { myDelegate = MySession() } let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: myDelegate, delegateQueue: nil) let loadDataTask = session.dataTaskWithURL(NSURL(string: myURL)!) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in // OMITTING ERROR CHECKING FOR BREVITY success(response: NSString(data: data!, encoding: NSASCIIStringEncoding) as! String) } loadDataTask.resume() } // extract data from redirect class func getRedirectionInfo(url: String) { getDataFromServerWithSuccess(url, noRedirect: true) {(data) -> Void in if let html = data { if html.rangeOfString("<html>\n<head><title>Bitly</title>", options: .RegularExpressionSearch) != nil { print("success: redirection was prevented") } else { print("failure: redirection went through") } } } } } MySession.getRedirectionInfo("http://bit.ly/filmenczer") 
+1
source

Source: https://habr.com/ru/post/983845/


All Articles