Preventing URLSession redirect in Swift

后端 未结 3 736
迷失自我
迷失自我 2021-02-14 02:59

I need to fetch a redirecting URL but prevent redirection in Swift. From other posts and Apple docs I understand I must implement the delegate method URLS

相关标签:
3条回答
  • 2021-02-14 03:18

    I also found the solution helpful, but I am using Swift 4.2 in my current project.

    So, here is an adapted shorter version of the solution above, that also works with Swift 4.2 and Xcode 10.

    import Foundation
    import PlaygroundSupport
    
    PlaygroundPage.current.needsIndefiniteExecution = true
    
    class MySession: NSObject, URLSessionTaskDelegate {
    
        func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
            completionHandler(nil)
        }
    }
    
    func getDataFromServerWithSuccess(myURL: String, noRedirect: Bool) {
        let myDelegate: MySession? = noRedirect ? MySession() : nil
    
        let session = URLSession(configuration: URLSessionConfiguration.default, delegate: myDelegate, delegateQueue: nil)
        let loadDataTask = session.dataTask(with: URL(string:myURL)!) { (data, response, error) in
    
            // OMITTING ERROR CHECKING FOR BREVITY
            if let data = data {
                if let dataString = String(bytes: data, encoding: .utf8) {
                    print(dataString)
                    if dataString.contains("Bitly") == true {
                        print("success: redirection was prevented")
                    } else {
                        print("failure: redirection went through")
                    }
                }
            }
        }
        loadDataTask.resume()
    }
    
    getDataFromServerWithSuccess(myURL: "http://bitly.com/filmenczer", noRedirect: true)
    
    0 讨论(0)
  • 2021-02-14 03:26

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

    1. You never set the delegate property on the NSURLSession instance that you're using to make the request. Without the delegate property set, your delegate methods won't ever be called. Instead of getting NSURLSession.sharedSession(), look at the NSURLSession(configuration:delegate:delegateQueue:) initializer. The first and last parameters can be NSURLSessionConfiguration.defaultSessionConfiguration() and nil, respectively, see below for more about the delegate.

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

    2. You'll have to refactor somewhat to use MySession as a delegate, since you're using class methods to make the request. You need an instance to use as the session's delegate.

    I took a short and incomplete route to having the delegate pick up on the redirect with this alternate code—you'll need to refactor as in #3 to make sure 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 that helps!

    0 讨论(0)
  • 2021-02-14 03:36

    Minor adjustments to the solutions proposed above. 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")
    
    0 讨论(0)
提交回复
热议问题