美文网首页工作生活
2019-07-01 NSURLProtocol 拦截 NSUR

2019-07-01 NSURLProtocol 拦截 NSUR

作者: 零零321 | 来源:发表于2019-07-01 09:48 被阅读0次

    原文:https://blog.csdn.net/yunqiinsight/article/details/80134267

    https://github.com/ChenYilong/CYLCURLNetworking?spm=a2c4e.11153959.blogcont543412.13.1bda7efeTdgxCQ

    NSURLProtocol 拦截 NSURLSession 请求时body丢失问题解决方案探讨

    在支持POST请求过程中会遇到丢失 body的 问题,有以下几种解决方法:

    换用 NSURLConnection。NSURLConnection 与 NSURLSession

    相比会遇到较多的性能问题,同时Apple的一些新特性也无法使用,终究会被淘汰,不作考虑。

    body放header的方法,2M以下没问题,超过2M会导致请求延迟,超过 10M 就直接 Request timeout。而且无法解决

    Body 为二进制数据的问题,因为Header里都是文本数据。

    换用 Get 请求,不使用 Post 请求。这个也是可行的,但是毕竟对请求方式有限制,终究还是要解决 Post

    请求所存在的问题。如果是基于旧项目做修改,则侵入性太大。这种方案适合新的项目。

    另一种方法是我们下面主要要讲的,使用 HTTPBodyStream 获取 body,并赋值到 body

    中,具体的代码如下,可以解决上面提到的问题:

    //

    //  NSURLRequest+CYLNSURLProtocolExtension.h

    //

    //

    //  Created by ElonChan on 28/07/2017.

    //  Copyright © 2017 ChenYilong. All rights reserved.

    //

    #import <Foundation/Foundation.h>

    @interface NSURLRequest (CYLNSURLProtocolExtension)

    - (NSURLRequest *)cyl_getPostRequestIncludeBody;

    @end

    //

    //  NSURLRequest+CYLNSURLProtocolExtension.h

    //

    //

    //  Created by ElonChan on 28/07/2017.

    //  Copyright © 2017 ChenYilong. All rights reserved.

    //

    #import "NSURLRequest+CYLNSURLProtocolExtension.h"

    @implementation NSURLRequest (CYLNSURLProtocolExtension)

    - (NSURLRequest *)cyl_getPostRequestIncludeBody {

        return [[self cyl_getMutablePostRequestIncludeBody] copy];

    }

    - (NSMutableURLRequest *)cyl_getMutablePostRequestIncludeBody {

        NSMutableURLRequest * req = [self mutableCopy];

        if ([self.HTTPMethod isEqualToString:@"POST"]) {

            if (!self.HTTPBody) {

                NSInteger maxLength = 1024;

                uint8_t d[maxLength];

                NSInputStream *stream = self.HTTPBodyStream;

                NSMutableData *data = [[NSMutableData alloc] init];

                [stream open];

                BOOL endOfStreamReached = NO;

                //不能用 [stream hasBytesAvailable]) 判断,处理图片文件的时候这里的[stream hasBytesAvailable]会始终返回YES,导致在while里面死循环。

                while (!endOfStreamReached) {

                    NSInteger bytesRead = [stream read:d maxLength:maxLength];

                    if (bytesRead == 0) { //文件读取到最后

                        endOfStreamReached = YES;

                    } else if (bytesRead == -1) { //文件读取错误

                        endOfStreamReached = YES;

                    } else if (stream.streamError == nil) {

                        [data appendBytes:(void *)d length:bytesRead];

                    }

                }

                req.HTTPBody = [data copy];

                [stream close];

            }

        }

        return req;

    }

    @end

    在用于拦截请求的 NSURLProtocol 的子类中实现方法 +canonicalRequestForRequest: 并处理 request 对象:

    + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {

      return [request cyl_getPostRequestIncludeBody];

    }

    +[NSURLProtocol canInitWithRequest:] 负责筛选哪些网络请求需要被拦截

    +[NSURLProtocol canonicalRequestForRequest:] 负责对需要拦截的网络请求NSURLRequest 进行重新构造。

    这里有一个注意点:+[NSURLProtocol canonicalRequestForRequest:] 的执行条件是 +[NSURLProtocol canInitWithRequest:] 返回值为 YES。

    注意在拦截 NSURLSession 请求时,需要将用于拦截请求的 NSURLProtocol 的子类添加到 NSURLSessionConfiguration 中,用法如下:

      NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

        NSArray *protocolArray = @[ [CYLURLProtocol class] ];

        configuration.protocolClasses = protocolArray;

        NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    更新:处理之后还是无效,把post换成get。。

    相关文章

      网友评论

        本文标题:2019-07-01 NSURLProtocol 拦截 NSUR

        本文链接:https://www.haomeiwen.com/subject/nkvwcctx.html