BBABaseAPIRequest.h 13.8 KB
//
//  BBABaseAPIRequest.h
//  BBAPods
//
//  Created by mengxiangping on 16/10/10.
//  Copyright © 2016年 Baidu. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <BBAAPIRequest/BBABaseAPIRequest+deprecated.h>

@class BBABaseAPIRequest;
@class BBAAPIRequestManager;

NS_ASSUME_NONNULL_BEGIN
//   业务方标识(用于打点)
typedef NSUInteger APIRequestFrom;
FOUNDATION_EXPORT APIRequestFrom const APIRequestFromUnknown;

typedef NSUInteger APIRequestSubFrom;
FOUNDATION_EXPORT APIRequestSubFrom const APIRequestSubFromDefault;

///  HTTP Request Methods.
typedef NS_ENUM(NSInteger, APIRequestMethod) {
    APIRequestMethodGET = 0,
    APIRequestMethodPOST,
    APIRequestMethodHEAD,
    APIRequestMethodPUT,
    APIRequestMethodDELETE,
    APIRequestMethodPATCH,
};

typedef NS_ENUM(NSInteger, APISerializerType) {
    
    APISerializerTypeNSData,    //返回数据为 NSData
    APISerializerTypeString,    //返回数据为 NSString
    APISerializerTypeJSON       //返回数据为 JSON
    
};

//  Request Priority
typedef NS_ENUM(NSInteger, APIRequestPriority) {
    APIRequestPriorityLow,
    APIRequestPriorityDefault,
    APIRequestPriorityHigh,
    APIRequestPriorityVeryHigh  //  11.0 新增,目前仅限Feed刷新使用
};


// Error Domains
FOUNDATION_EXPORT NSString *const APIRequestErrorDomain;

// Error Codes
typedef NS_ENUM(NSInteger, APIRequestErrorCode) {
    APIRequestErrorCodeJSONParse = 0,
    APIRequestErrorCodeTaskNil,
    APIRequestErrorCodeMoveDownloadFileFail,
    APIRequestErrorCodeBusy,
    APIRequestErrorCodeInvalidURL,
    APIRequestErrorCodeResumeDataNil,
    APIRequestErrorCodeResumedDownloadFail
};

typedef NS_ENUM(NSUInteger, APIRequestQuicStatus) {
    APIRequestQuicStatusDisable,
    APIRequestQuicStatusEnableBySdt,
    APIRequestQuicStatusEnableByNqe
};

/// BaseAPIRequest的统计信息类
/// 使用方法:1. 设置BBABaseAPIRequest.needMetrics  = YES; 2. 设置didCollectMetricsBlock回调block
/// Note: 如果使用NSURLSession引擎(netEngine = 1/2),Metric信息只在iOS10.0及以上系统有效;如果使用Cronet引擎,无系统限制。
@interface BBAAPIRequestMetricsInfo : NSObject
//  NetworkInfo
@property (atomic, assign, readonly) NSInteger ipStack;     //  0.未知 1.v4-only 2.v6-only 3.双栈
@property (atomic, assign, readonly) NSInteger netQuality;  //  1.好网 2.弱网 3.无网 4.未知
@property (atomic, assign, readonly) BOOL isWeakNet;        //  是否弱网
@property (atomic, copy,   readonly) NSString *netTypeBegin;//  请求发送前的网络制式类型
@property (atomic, copy,   readonly) NSString *netTypeEnd;  //  请求结束时的网络制式类型
@property (atomic, assign, readonly) BOOL netTypeChanged;   //  请求过程中网络制式是否变化
@property (atomic, copy,   readonly) NSString *clientIP;    //  出口IP
@property (atomic, assign, readonly) BOOL viaVPN;           //  是否有VPN

/// NetEngine
@property (atomic, assign, readonly) NSUInteger netEngine;  //  网络引擎类型, 1:AFN; 2.NSURLSession; 3:CroNet(TurboNet in baidu)

/// Success/Fail
@property (atomic, assign, readonly) BOOL isSuccess;        //  成功与否
@property (atomic, assign, readonly) BOOL canceled;         //  主动取消
@property (atomic, assign, readonly) NSInteger errCode;     //  错误码
@property (atomic, assign, readonly) NSInteger underlyErrCode;     //  详细错误码

//  TimingInfo
@property (atomic, strong, readonly) NSDate *startTime;     //  请求开始时间
@property (atomic, strong, readonly) NSDate *resumeTime;    //  请求发送时间
@property (atomic, strong, readonly) NSDate *finishTime;    //  请求结束时间
@property (atomic, assign, readonly) NSTimeInterval queueDuration;  //  排队耗时
@property (atomic, assign, readonly) NSTimeInterval dnsDuration;    //  dns 耗时
@property (atomic, assign, readonly) NSTimeInterval tcpDuration;    //  tcp 耗时
@property (atomic, assign, readonly) NSTimeInterval sslDuration;    //  ssl 耗时
@property (atomic, assign, readonly) NSTimeInterval ttfbDuration;   //  ttfb 耗时
@property (atomic, assign, readonly) NSTimeInterval completeWaitDuration;//  回调等待耗时

/// ConnectionInfo
@property (atomic, assign, readonly) BOOL socketReused;     //  是否复用连接
@property (atomic, assign, readonly) BOOL viaProxy;         //  是否通过代理
@property (atomic, copy,   readonly) NSString *localIPPort; //  local IP和端口号 (NSURLSession iOS13+; Cronet iOS9+)
@property (atomic, copy,   readonly) NSString *remoteIPPort;//  remote IP和端口号 (NSURLSession iOS13+; Cronet iOS9+)

/// HttpInfo
@property (atomic, copy,   readonly) NSString *protocol;    //  HTTP协议类型
@property (atomic, assign, readonly) NSInteger statusCode;  //  HTTP状态码
@property (atomic, assign, readonly) NSInteger requestBodyLength;   //  请求上行包大小
@property (atomic, assign, readonly) NSInteger responseLength;      //  请求响应包大小

@end

typedef void(^APIRequestCompletionBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest);
typedef void(^APIRequestFailureBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, __kindof NSError* _Nonnull error);
typedef void(^APIRequestProgressCompletion)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, __kindof NSProgress* _Nonnull progress);
typedef void(^APIRequestStartedBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest);
typedef void(^APIRequestDidReceiveResponseHeadersBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, NSDictionary *responseHeaders);
typedef void(^APIRequestDidReceiveDataBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, NSData *data);
typedef NSURLRequest*  _Nullable (^APIRequestWillRedirectBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, NSURLRequest* _Nonnull newURLRequest);
typedef void(^APIRequestDidReceiveBytesBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, NSInteger bytes);
typedef void(^APIRequestStreamDownloadBytes)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, const void* bytes, NSUInteger length);
typedef void(^APIRequestDidResumeDownloadBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, NSDictionary *responseHeaders, int64_t offset, int64_t expectedTotalBytes);
typedef void(^APIRequestDidCollectMetricsBlock)(__kindof BBABaseAPIRequest* _Nonnull apiRequest, BBAAPIRequestMetricsInfo* _Nonnull metrics);

@interface BBABaseAPIRequest : NSObject <NSCopying>

- (instancetype)initWithURLRequest:(NSURLRequest*)urlRequest;

// 请求唯一ID,可用来追踪日志等, 存在扩展Header中("X-Bd-Traceid":"xxx")
@property (nonatomic, copy, readonly) NSString *bdTraceId;

// 回调
@property (atomic, nullable) APIRequestCompletionBlock completionBlock; // 请求成功的回调
@property (atomic, nullable) APIRequestFailureBlock failureBlock; // 请求失败的回调
@property (nonatomic, nullable) APIRequestProgressCompletion progressBlock; // 上传/下载请求进程回调
@property (nonatomic, nullable) APIRequestStartedBlock startedBlock; // 请求开始的回调
@property (nonatomic, nullable) APIRequestDidReceiveResponseHeadersBlock didReceiveResponseHeadersBlock; // 收到Response Headers 的回调
@property (nonatomic, nullable) APIRequestDidReceiveDataBlock didReceiveDataBlock; // 收到数据时的回调
@property (nonatomic, nullable) APIRequestWillRedirectBlock willRedirectBlock; // 将要重定向时的回调
@property (nonatomic, nullable) APIRequestDidReceiveBytesBlock didReceiveBytesBlock; // 下载请求收到字节数(单次)的回调
@property (nonatomic, nullable) APIRequestStreamDownloadBytes streamDownloadBytesBlock; //  流式下载回调
@property (nonatomic, nullable) APIRequestDidResumeDownloadBlock didResumeDownloadBlock; // 断点续传恢复下载回调
@property (nonatomic, nullable) APIRequestDidCollectMetricsBlock didCollectMetricsBlock; // 请求Metric打点回调
@property (nonatomic, strong, nullable) dispatch_queue_t callbackQueue;

@property (nonatomic, weak, nullable, readonly) NSURLSession *session;

@property (nonatomic, strong, nullable, readonly) NSURLSessionTask *task;
@property (nonatomic, strong, readonly) NSNumber *taskIdentfier;
/// The request’s cache policy
@property NSURLRequestCachePolicy cachePolicy;

//响应内容
@property (atomic, copy, nullable, readonly) NSDictionary * responseHeaders;
@property (nonatomic, readonly) NSInteger responseStatusCode; //状态码
@property (nonatomic, strong, nullable, readonly) NSString *responseString;
@property (nonatomic, strong, nullable, readonly) NSData *responseData;
@property (nonatomic, strong, nullable, readonly) id responseJSON;

@property (atomic, strong, nullable) NSURLRequest *urlRequest;   //URLRequest 为 HTTP 协议中的请求。  APIRequest 代表我们网络库的封装请求, 两者概念不同。
@property (nonatomic, strong, nullable, readonly) NSURLResponse *urlResponse;

//错误信息
@property (nonatomic, strong, nullable, readonly) NSError *error;
@property (nonatomic, assign, readonly) NSInteger errCode;

//附加信息 - 目前用作 DNS TYPE 的记录
@property (nonatomic, strong) NSString *info;

//自定义附加信息
@property (nonatomic, copy) NSDictionary *userInfo;

//自定义日志信息(会被加网络日志中)
@property (nonatomic, copy) NSDictionary *userLogInfo;

// 是否为异步请求,默认为异步请求,请勿在主线程发起同步请求, 11.1 版本已废弃,不再提供对同步请求的支持
@property (nonatomic, assign) BOOL isAsynchronous __attribute__ ((deprecated));

// HTTP 协议

// 请求 API 的 URL
- (nonnull NSString *) apiURL;
// 请求方法
- (APIRequestMethod) requestMethod;
// 请求参数
- (nullable id) requestParams;
// 直接配置PostBodyData(会忽略requestParams)
@property (nonatomic, strong) NSData * postBodyData;
//  是否开启业务打点
@property (nonatomic, assign) BOOL needRequestFromStat;
//  请求业务方标识,常量值由业务方自己定义
@property (nonatomic, assign) APIRequestFrom requestFrom;
//  子业务方标识,常量值由业务方自己定义
@property (nonatomic, assign) APIRequestSubFrom requestSubFrom;
//  是否携带NSHTTPCookieStorage中Cookies, 默认为YES
@property (nonatomic, assign) BOOL shouldHandleCookies;
//  请求Timeout Interval(单位秒)
@property (nonatomic, assign) NSTimeInterval requestTimeout;

//  请求优先级配置
@property (nonatomic, assign) APIRequestPriority priority;

//  下载请求存储路径
@property (nonatomic, strong) NSString *downloadTargetPath;
@property (nonatomic, assign, readonly) uint64_t downloadTotalSize;
@property (nonatomic, assign, readonly) uint64_t downloadWrittenSize;

//  是否支持断点续传
@property (nonatomic, assign) BOOL allowDownloadResume;
//  allowDownloadResume=YES时生效. 若指定, 将在该文件基础上进行续传, 完成后删除; 若不指定, 会在tmp目录下创建临时文件来支持续传
@property (nonatomic, strong) NSString *resumeTemporaryPath;
@property (nonatomic, strong, readonly) NSDictionary *resumeDataDict;

//  是否支持流式下载, 暂不支持断点续传, 流式数据通过streamDownloadBytesBlock接收
@property (nonatomic, assign) BOOL allowStreamDownload;

//  使用普通POST上传文件
@property (nonatomic, strong) NSString *uploadFileLocalPath;

// 上传Data
@property (nonatomic, assign) NSData *uploadBodyData;

//  使用multipart/formData POST上传
@property (nonatomic, assign) BOOL useMultipartFormDataPost;
//  使用multipart/formData    添加上传文件
- (void)addPartWithFile:(NSString *)filePath
               fileName:(NSString *)fileName
               mimeType:(NSString * _Nullable)mimeType
                  asKey:(NSString *)key;
//  使用multipart/formData    添加上传文件
- (void)addPartWithFileData:(NSData *)fileData
                   fileName:(NSString *)fileName
                   mimeType:(NSString * _Nullable)mimeType
                      asKey:(NSString *)key;
//  使用multipart/formData    添加key-value参数
- (void)addPartWithValue:(NSString *)value
                   asKey:(NSString *)key;

- (nullable NSDictionary *) requestHeaders;

// 数据解析逻辑

// 数据格式
- (APISerializerType) responseSerializer;

// JSON 验证规则
- (nullable id) jsonRules;


- (BOOL) validateJSON: (nonnull id) json error: (NSError *_Nullable * _Nullable) error;

// 发起请求
- (void) start;
- (void) startWithCompletionBlock: (nonnull APIRequestCompletionBlock) completion;
- (void) startWithCompletionBlock: (nonnull APIRequestCompletionBlock) completion failure: (nullable APIRequestFailureBlock) failure;

- (void) cancel;

// 请求是否被取消
@property (nonatomic, assign, readonly) BOOL isCancelled;

/// TimeDate
@property (nonatomic, strong, readonly) NSDate *startDate;
@property (nonatomic, strong, readonly) NSDate *endDate;

// 获取断点续传临时文件大小
- (NSInteger)getResumeTempFileSize;

/// Metrics
@property (nonatomic, assign) BOOL needMetrics;

@property (nonatomic, assign, readonly) APIRequestQuicStatus quicStatus;

@property (nonatomic, assign) BOOL isImmediateRequest; // 若设置为 YES,请求不进队列立即发送

@property (nonatomic, copy, readonly) NSString *tag; // HTTPManager tag

@end

/// 弃用属性
@interface BBABaseAPIRequest (deprecated)
@property (atomic, strong, readonly) BBAAPIRequestMetrics *requestMetrics __deprecated; // 请求打点信息,请求提交到网络库时填入
@property (atomic, strong, readonly) BBAAPIResponseMetrics *responseMetrics __deprecated; // 应答打点信息,请求完成时填入
@property (nonatomic, assign) BOOL useNewRequestManager __deprecated; // TODO: 网络门面重构全量后,须移除
@property (nonatomic, strong, readonly) NSDate *enqueueDate __deprecated;
@property (nonatomic, nullable) APIRequestDidCollectRequestMetricsBlock didCollectRequestMetricsBlock __deprecated; // 请求打点回调
@property (nonatomic, nullable) APIRequestDidCollectResponseMetricsBlock didCollectResponseMetricsBlock __deprecated; // 响应打点回调
@end
NS_ASSUME_NONNULL_END