使用Alamofire在Swift中防止重定向响应

3

我正在寻找如何防止Web API请求时重定向响应(状态码3xx)的示例代码。我使用的是Alamofire 1.2的Swift版本。 我已经尝试过:

delegate.taskWillPerformHTTPRedirection = { (session: NSURLSession!, task: NSURLSessionTask!, response: NSHTTPURLResponse!, request: NSURLRequest!) in
            return nil
        }

但是不起作用。

我也尝试过:https://github.com/Alamofire/Alamofire/pull/350/files 并且将我的代码更改为:

    var acc = self.txtAccount.text
    var pwd = self.txtPassword.text
    var url : String = "http://10.1.0.2:8081/wordpress/wp-json/users/me"
    let delegate = Alamofire.Manager.sharedInstance.delegate
    delegate.taskWillPerformHTTPRedirection = { (session: NSURLSession!, task: NSURLSessionTask!, response: NSHTTPURLResponse!, request: NSURLRequest!) in

        var request = NSMutableURLRequest(URL: NSURL(string: url)!)
        request.HTTPMethod = "GET"

        var credential = "\(acc):\(pwd)"
        var authData = credential.dataUsingEncoding(NSUTF8StringEncoding)
        var encodedAuthData = authData?.base64EncodedStringWithOptions(nil)
        var authValue = "Basic \(encodedAuthData!)"

        request.setValue(authValue, forHTTPHeaderField: "Authorization")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        return request
    }

    //I've implemented URLRequestConvertible 'Router'. it also have call the same above url
    Alamofire.request(Router.Authorize(acc, pwd))
        .response({(request, response, data, error) in
            println(request)
        })

但是它没有起作用,似乎变成了无限循环。我在Charles上进行了测试。


1
如果你在那个闭包里面加入一个 println("Redirection is calling my closure"),你能看到它被调用了吗?或者放置一个断点? - cnoon
如果您尚未设置delegate,它可以为nil。 - onmyway133
5个回答

5

使用AlamoFire 2.4 (Xcode7)的备用(代码段)解决方案。在我的情况下,我总是期望重定向。(我正在展开一个缩短的链接。) 如果请求响应中的完成运行,则对我来说是一个错误。

func printRedirectUrl() {

    // taskWillPerformHTTPRedirectionWithCompletion: ((NSURLSession, NSURLSessionTask, NSHTTPURLResponse, NSURLRequest, NSURLRequest? -> Void) -> Void)?
    Alamofire.Manager.sharedInstance.delegate.taskWillPerformHTTPRedirectionWithCompletion = { session, task, response, request, completion in
        // request.URL has the redirected URL inside of it, no need to parse the body
        print("REDIRECT Request: \(request)")
        if let url = request.URL {
            print("Extracted URL: \(url)")
        }
        Alamofire.Manager.sharedInstance.delegate.taskWillPerformHTTPRedirection = nil // Restore redirect abilities
        return
    }

    // We expect a redirect, so the completion of this call should never execute
    let url = NSURL(string: "https://google.com")
    let request = Alamofire.request(.GET, url!)
    request.response { request, response, data, error in
        print("Logic Error, response should NOT have been called for request: \(request)")
        Alamofire.Manager.sharedInstance.delegate.taskWillPerformHTTPRedirection = nil // Restore redirect abilities - just in case
    }
}

重定向请求: { URL: https://www.google.com/ }

提取的URL: https://www.google.com/


3

你好,这实际上很简单。

Alamofire有一个重定向器,它会

示例

let request = AF.request("https://google.com",method: .post,parameters: parameters)
.cURLDescription { description in
            debugPrint(description)
        }
        let redirector = Redirector(behavior: .doNotFollow)
        request.redirect(using: redirector)

这样就不会重定向了

在高级用法部分的文档中也有相关说明


3
在Swift 4中,
let delegate = Alamofire.SessionManager.default.delegate

        delegate.taskWillPerformHTTPRedirection = { (session, task, response, request) -> URLRequest? in
           // print("REDIRECT Request: \(request)")
            return nil
        }

1
运行得非常好!谢谢,伙计! - Cleversou

2
看起来返回nil可能会导致死锁。相反,尝试使用相同的原始URL创建一个新的NSURLRequest。请参见@jhersh在以前Alamofire PR中的注释以及他的测试中的评论和实现。
如何停止重定向
func disallowRedirect() {
    let URL = "http://google.com/"
    let delegate = Alamofire.Manager.sharedInstance.delegate

    delegate.taskWillPerformHTTPRedirection = { session, task, response, request in
        return NSURLRequest(URL: NSURL(string: URL)!)
    }

    let request = Alamofire.request(.GET, URL)
    request.response { request, response, data, error in
        println("Request: \(request)")
        println("Response: \(response)")
        println("Data: \(NSString(data: data as! NSData, encoding: NSUTF8StringEncoding))")
        println("Error: \(error)")
    }
}

disallowRedirect()

你不能将nil传递给NSURLSessionTaskDelegate方法的completionHandler,看起来像是一个错误。我将为此提交一份radar,并在完成后发布错误报告的链接。

你不想在 taskWillPerformHTTPRedirection 中获取响应数据,而是要在响应序列化器中获取。如果你正确地禁用了重定向,你应该能够从原始请求中接收到响应。请参阅此文章以获取更多信息。 - cnoon
起初,我想禁用重定向并在response方法内接收响应数据。 在您上面的评论提到返回nil会导致死锁之后,@jhersh的测试也有评论`+ // TODO:URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:
  • //建议返回nil应该拒绝重定向,但这会导致死锁/超时 + 所以我正在寻找如何在taskWillPerformHTTPRedirection`中访问原始请求的数据。 现在您建议我禁用重定向。 我想知道我该如何做?
- khangcv
1
亲爱的朋友,代码似乎陷入了无限循环。我已经更清楚地更新了我的问题。我无法在PG上测试,因为不知道如何在PG上导入alamofire。 - khangcv
@khangcv,Alamofire 项目本身就有一个游乐场。你只需要下载该项目或从 Github 克隆它。然后打开工作区,再打开游乐场。粘贴我写的代码,它将按预期工作。由于您的代码中出现了无限循环,我建议您尝试返回创建 NSURLRequest 的第一行。也许通过添加所有其他标头等,您在技术上触发了另一个请求?我不是完全确定,因为我无法尝试您的代码。 - cnoon
1
当我在alamorefire playground上测试并使用示例URL:google.com时,结果是消息Optional(Error Domain = NSURLErrorDomain Code = -1007“太多的HTTP重定向”。请求循环约16次并停止。 - khangcv
显示剩余3条评论

0

我不知道你使用的 Alamofire 版本是否支持公共委托。上次我检查时,委托是私有的。我正在使用 @jhersh 所做的更改。您可以通过关注 GitHub pr 来查看他的添加和如何使用委托。https://github.com/Alamofire/Alamofire/issues/314


在 Alamofire 1.2.0 版本中,委托及其各种重写闭包已正式开放。 - cnoon
谢谢提供的信息。由于我正在使用iOS 7,无法直接使用发布版本,因此我使用自己的版本,并使用结构体等来模拟框架。 - Meanteacher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接