关于iOS的重定向

本文详细解释了iOS中Webview如何判断HTTP重定向,以及如何在App内完成URL重定向,包括使用NSURLConnectionDataDelegate处理重定向请求,并介绍了在UIWebView、NSURLConnection和NSURLSession中拦截302重定向请求的不同方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重定向与转发经常不明白是什么意思
现在来解释一下:

请求重定向相当于是重新发送了一次请求,而请求转发是一次请求;

1>请求重定向:就好比我们找一个A广告公司给设计名片,A明确告诉我们他们不会设计,就让我们找B公司,结果B公司给我设计好了,所以我们会对外宣称是B公司给我们设计的名片,(所以我们就相当于发送了两次次请求,URL地址栏里就从A变成了B公司)

一、ios webview怎么判断http是重定向

public boolean shouldOverrideUrlLoading (WebView view, String url) {  
     HitTestResult hit = view.getHitTestResult();  
     if (hit != null) {  
                Intent intent = new Intent();  
                intent.setAction( "android.intent.action.VIEW");  
                Uri content_url = Uri. parse(url);  
                intent.setData(content_url);  
                 context.startActivity(intent);  
                 return true;  
     } else {  
           view.loadUrl(url);  
            return true;  
     }  
}

二、iOS应用中URL地址如何重定向

例如http://www.google.com谷歌的首页
大家都知道现在浏览器中打开google.com的话事实上会变成http://www.google.com.hk。显然是网址被重定向的结果

如何在app中完成重定向呢
使用NSURLConnetion类的NSURLConnectionDataDelegate委托
NSURLConnectionDataDelegate委托中的这个方法

- (void)viewDidLoad {  
    [super viewDidLoad];  

    NSURL *url = [NSURL URLWithString:@"http://www.google.com"];  
    NSURLRequest *request = [NSURLRequest requestWithURL:url];  
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];  

    if (!connection) {  
        NSLog(@"FAIL");  
    }  
}  

- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response {  
    NSLog(@"====================================");  
    NSLog(@"will send request\n%@", [request URL]);  
    NSLog(@"redirect response\n%@", [response URL]);  
    return request;  
}  

委托方法在请求将要被发送出去之前就会调用
返回值是一个NSURLRequest即那个真正将要被发送的请求
第二个参数request就是被重定向处理过后的请求 在这里就可以拿到需要的URL
第三个参数response是一个将要触发重定向的请求
这里把request跟response中的URL打出来看一下

====will send request====  
http://www.google.com/  
====redirect response====  
(null)  

====will send request====  
http://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1347589441099727&usg=AFQjCNEsBYcrlh_jqpBWRwsc0NpBj2_lFg  
====redirect response====  
http://www.google.com/  

====will send request====  
http://www.google.com.hk/  
====redirect response====  
http://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1347589441099727&usg=AFQjCNEsBYcrlh_jqpBWRwsc0NpBj2_lFg  

由以上结果可知:
<1> 第一次调用 没有进行重定向处理 所以redirect response是null
而想要被发送的请求就是www.google.com
<2> 第二次redirect response就不是null了,就是第一次中的那个request,也就是说这一次的重定向是由www.google.com这个URL引发的
而重定向的结果就是http://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1347589441099727&usg=AFQjCNEsBYcrlh_jqpBWRwsc0NpBj2_lFg
<3> 当然http://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1347589441099727&usg=AFQjCNEsBYcrlh_jqpBWRwsc0NpBj2_lFg这个网址不是那个熟悉的网址,因为还要一次重定向,这次就跟上面一样了 那个很长的URL这次出现在了redirect response里,触发了这次重定向
结果可以看到,就是那个熟悉的www.google.com.hk
<4> 当获得想要的URL以后可以调用[connection cancel];方法来取消连接
并返回nil就好了
三、IOS拦截重定向请求(302)的几种方式

在多数情况下,我们做的网络请求是返回200状态码的,但也有返回302的时候,比如使用基于Oauth2认证协议的API时,在认证阶段,需要提供一个回调地址,当用户授权后,服务器会返回一个302 Response,Response Header中会一个Location字段,包含了我们的回调地址,同时会有一个Code参数。我们在程序中该如何处理这个请求,并拿到这个Code参数呢。下面由我来为大家讲解下几种方式的做法,各取所需。

《1》UIWebView控件
这是最常见的做法,但是UIWebView是无法拦截302请求的,只能等待整个流程完成回到回调地址时,我们在webView控件的webViewDidFinishLoad回调方法处理数据。
《2》基于NSURLConnection来设置拦截

class LoginViewController: UIViewController,NSURLConnectionDataDelegate {
    func connection(){
        //创建一个可以编辑的NSURLRequest
        var mutableRequest = NSMutableURLRequest(URL: NSURL(string: "http://devonios.com")!)
        mutableRequest.HTTPMethod = "POST"
        //设置POST请求的表单数据
        mutableRequest.HTTPBody = paramString.dataUsingEncoding(NSStringEncoding.allZeros, allowLossyConversion: true)
        //使用构造函数方法创建一个NSURLConnection的实例
        var connection:NSURLConnection = NSURLConnection(request: mutableRequest, delegate: self)!
        connection.start()
    }
    //处理重定向请求的方法
    func connection(connection: NSURLConnection, willSendRequest request: NSURLRequest, redirectResponse response: NSURLResponse?) -> NSURLRequest? {

        if let r = response{

            //当前重定向请求的url,包含了Code参数
            let requesturl = request.URLString

            //得到Code,由于Code参数设置了属性观察器,所以当Code被赋值时,会自动去获取Token
            self.code = requesturl.GetCode()

            //因为已经拿到Code了,所以拦截掉当前这个重定向请求,直接返回nil
            return nil
        }
        return request
    }
    //整个请求完成后,即拦截到302后,不再请求了就返回这里
    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
        if (某些判断条件){
            self.navigationController?.popViewControllerAnimated(true)
        }
    }
}

《3》基于NSURLSession类来设置拦截
NSURLSession是IOS 7中开始出现的全新的网络接口类,和NSURLConnection类似,同样需要设置delegate。

class MyRequestController:NSObject,NSURLSessionTaskDelegate {

    let session:NSURLSession?

    init(){
        let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
        session = NSURLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
    }

    deinit{
        session!.invalidateAndCancel()
    }
    //处理重定向请求,直接使用nil来取消重定向请求
    func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
        completionHandler(nil)
    }

    func sendRequest() {

        var URL = NSURL(string: "http://devonios.com")
        let request = NSMutableURLRequest(URL: URL!)
        request.HTTPMethod = "POST"

        request.HTTPBody = paramString.dataUsingEncoding(NSStringEncoding.allZeros, allowLossyConversion: true)

        let task = session!.dataTaskWithRequest(request, completionHandler: { (data : NSData!, response : NSURLResponse!, error : NSError!) -> Void in
            //由于拦截了302,设置了completionHandler参数为nil,所以忽略了重定向请求,这里返回的Response就是包含302状态码的Response了。
            let resp:NSHTTPURLResponse = response as! NSHTTPURLResponse
            println("包含302状态的Response Header字段 : \(resp.allHeaderFields)")  })
            task.resume()
    }
}

目前为止,我们通过为NSURLConnection或者NSURLSession设置一个Delegate,通过回调方法来拦截(其实就是返回个nil)。
参考资料http://devonios.com/intercept-302-request.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值