繁体   English   中英

在Swift中防止URLSession重定向

[英]Preventing URLSession redirect in Swift

我需要获取一个重定向URL,但是在Swift中阻止重定向 从其他文章和Apple文档中,我了解到我必须实现委托方法URLSession(session:, task:, willPerformHTTPRedirection response:, request:, completionHandler:)并通过完成闭包返回nil 但是我找不到迅速的例子,也找不到正确的方法。 下面的代码在操场上重现了我的问题:委托似乎没有被执行。

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

请保持温柔,我是新手。 预先感谢您的协助!

更新:非常感谢@nate,让我可以使用它。 关键见解在于,为了调用委托,必须将委托类传递NSURLSession()初始化程序,而不是使用NSURLSession.sharedSession() nil作为委托传递会产生习惯行为(带有重定向)。 这是代码的工作版本:

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")

当前的实现中有两件事妨碍您前进。

  1. 您永远不会在用于发出请求的NSURLSession实例上设置委托属性。 没有委托属性的设置,您的委托方法将永远不会被调用。 而不是获取NSURLSession.sharedSession() ,而是查看NSURLSession(configuration:delegate:delegateQueue:)初始化程序。 第一个和最后一个参数可以分别是NSURLSessionConfiguration.defaultSessionConfiguration()nil ,有关委托的更多信息,请参见下文。

    请注意,当您使用带有完成处理程序的session.dataTaskWithURL变体时,处理响应和数据传递的委托方法将被忽略,但仍使用身份验证和重定向处理程序。

  2. 由于使用类方法发出请求,因此您必须进行一些重构才能将MySession用作委托。 您需要一个实例用作会话的委托。

我使用了一条简短而又不完整的方法来使委托使用此备用代码来进行重定向-您需要按照#3进行重构,以确保仍然可以调用回调:

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()
}

希望有帮助!

对上述解决方案进行了细微调整。 这适用于XCode 7中的Swift 2。

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")

我也发现该解决方案很有帮助,但是我在当前项目中使用的是Swift 4.2。

因此,这是上述解决方案的经过改编的简短版本,也可用于Swift 4.2Xcode 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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM