AFN源码阅读-AFURLRequestSerializatio

2019-08-19  本文已影响0人  ToBeABetter_man
/**
    返回一个基于RFC 3986协议的百分比转义字符串 
**/ 
FOUNDATION_EXPORT NSString * AFPercentEscapedStringFromString(NSString *string);

在网络请求中,由于各种原因,所以我们的URL需要进行编码,因为URL中有些字符会引起歧义。

例如URL参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?q=abc&ie=utf-8。如果你的value字符串中包含了=或者&,那么势必会造成接收Url的服务器解析错误,因此必须将引起歧义的&和=符号进行转义,也就是对其进行编码。

又如,Url的编码格式采用的是ASCII码,而不是Unicode,这也就是说你不能在Url中包含任何非ASCII字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。

/*
一个用来帮助将传进来的参数编码成查询字符串追加到URL后面
*/
FOUNDATION_EXPORT NSString * AFQueryStringFromParameters(NSDictionary *parameters);

下面是一个AFURLRequestSerialization协议用来帮助URL进行编码的协议

/**
 为HTTP请求中的参数进行编码的序列化协议
请求序列化可以将参数编码为查询字符串、HTTP主体,并根据需要设置适当的HTTP头字段。

例如,JSON请求序列化程序可以将请求的HTTP主体设置为JSON表示,并将“content-type”HTTP头字段值设置为“application/json”。
 */
@protocol AFURLRequestSerialization <NSObject, NSSecureCoding, NSCopying>

/**
 返回一个基于原始请求将传入参数进行编码后的请求

 @param request 原始的请求
 @param parameters 要进行编码的参数
 @param error 在对请求参数进行编码时发生的错误

 @return A serialized request.
 */
- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                               withParameters:(nullable id)parameters
                                        error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;

@end

AFHTTPRequestSerializer

/**
    一个序列化时的枚举,目前就一个默认枚举值
 */
typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) {
    AFHTTPRequestQueryStringDefaultStyle = 0,
};


/**
 `AFHTTPRequestSerializer`遵守`AFURLRequestSerialization` 和`AFURLResponseSerialization` 协议, 提供查询字符串/url表单编码参数序列化和默认请求头的具体基本实现,以及响应状态代码和内容类型验证。

任何处理HTTP的请求或响应序列化程序都鼓励将` AFHTTPRequestSerializer`子类化,以确保一致。
 */
@interface AFHTTPRequestSerializer : NSObject <AFURLRequestSerialization>

/**
参数序列化时的编码类型
默认使用 `NSUTF8StringEncoding`.
 */
@property (nonatomic, assign) NSStringEncoding stringEncoding;

/**
进行请求时是否使用蜂窝网络 默认为YES
 */
@property (nonatomic, assign) BOOL allowsCellularAccess;

/**
创建Request时的缓存策略 
默认为`NSURLRequestUseProtocolCachePolicy`.
 */
@property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;

/**
 创建的请求是否应使用默认的cookie处理
默认为`YES`
 */
@property (nonatomic, assign) BOOL HTTPShouldHandleCookies;

/**
 创建的请求是否可以在接收到之前的请求响应之前继续传输数据。
默认为NO
 */
@property (nonatomic, assign) BOOL HTTPShouldUsePipelining;

/**
已创建请求的网络服务类型。
默认为 `NSURLNetworkServiceTypeDefault`.

typedef NS_ENUM(NSUInteger, NSURLRequestNetworkServiceType)
{
    NSURLNetworkServiceTypeDefault = 0, // Standard internet traffic
    NSURLNetworkServiceTypeVoIP = 1,    // Voice over IP control traffic
    NSURLNetworkServiceTypeVideo = 2,   // Video traffic
    NSURLNetworkServiceTypeBackground = 3, // Background traffic
    NSURLNetworkServiceTypeVoice = 4,      // Voice data
    NSURLNetworkServiceTypeResponsiveData = 6, // Responsive data
    NSURLNetworkServiceTypeCallSignaling API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0)) = 11, // Call Signaling
};
 */
@property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType;

/**
多少秒后请求超时
默认 60秒
 */
@property (nonatomic, assign) NSTimeInterval timeoutInterval;

///---------------------------------------
/// @name Configuring HTTP Request Headers
///---------------------------------------

/**
要应用于序列化的默认HTTP请求头字段值。默认字段:

 - `Accept-Language` with the contents of `NSLocale +preferredLanguages`
 - `User-Agent` with the contents of various bundle identifiers and OS designations

 可以通过`setValue:forHTTPHeaderField:`方法增加或移除默认字段
 */
@property (readonly, nonatomic, strong) NSDictionary <NSString *, NSString *> *HTTPRequestHeaders;

/**
创建一个带默认配置的序列化对象
 */
+ (instancetype)serializer;

/**
设置HTTP客户端在请求对象中设置的HTTP头的值。如果为“nil”,则删除该头的现有值。
 */
- (void)setValue:(nullable NSString *)value
forHTTPHeaderField:(NSString *)field;

/**
    获取请求头里字段的值
 */
- (nullable NSString *)valueForHTTPHeaderField:(NSString *)field;

/**
设置授权验证
用客户端的请求对象通过用户名和密码进行Base64编码后的值来进行验证,并覆盖当前请求头任何存在的值。
 */
- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username
                                       password:(NSString *)password;

/**
清除请求头中存在的验证信息
 */
- (void)clearAuthorizationHeader;

///-------------------------------------------------------
/// @name Configuring Query String Parameter Serialization
///-------------------------------------------------------

/**
请求查询参数(query String)编码方式。默认为 `GET`, `HEAD`, and `DELETE`.
 */
@property (nonatomic, strong) NSSet <NSString *> *HTTPMethodsEncodingParametersInURI;

/**
  根据预先定义的样式之一设置查询字符串序列化方法。
  就是上面的那个枚举,目前只有一个枚举值
 */
- (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style;

/**
在block中自定义查询字符串的序列化方法

 */
- (void)setQueryStringSerializationWithBlock:(nullable NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block;

///-------------------------------
/// @name Creating Request Objects
///-------------------------------

/**
 Creates an `NSMutableURLRequest` object with the specified HTTP method and URL string.
根据HTTP请求方式和URL创建一个Request

如果请求方式为`GET`, `HEAD`, 或者`DELETE,那么参数会被构建成一个URL编码的查询字符串拼接在请求的URL路径后面。否则,参数将根据“ParameterEncoding”属性的值进行编码,并设置为请求体。

 */
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
                                 URLString:(NSString *)URLString
                                parameters:(nullable id)parameters
                                     error:(NSError * _Nullable __autoreleasing *)error;

/**
  创建一个用`multipart/form-data`方式进行编码的请求
(multipart/form-data是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。)

 多部分表单请求会自动流式处理,直接从磁盘读取文件,并在单个HTTP主体中读取内存中的数据。
生成的“NSMutableUrlRequest”对象具有“ HTTPBodyStream”属性,因此不要对此请求对象设置“ HTTPBodyStream”或“ HTTPBody”,因为它将清除多部分表单正文流。

 */
- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
                                              URLString:(NSString *)URLString
                                             parameters:(nullable NSDictionary <NSString *, id> *)parameters
                              constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                                                  error:(NSError * _Nullable __autoreleasing *)error;

/**
通过一个已有的请求创建一个删除“ HTTPBodyStream”属性的请求,并将其内容异步写入指定文件,完成后调用完成Block进行处理。

“ NSURLSessionTask”中存在一个Bug,它会导致请求在从HTTP主体流式传输内容时不发送请求头的“content-length”,
这在与Amazon S3 Web服务交互时明显存在的问题。
解决方案,我们可以通过拷贝一个用`multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error:`方法创建的或者其它带`HTTPBodyStream`属性的Request,然后将`HTTPBodyStream`设置为`nil`。
这里文件可以传递给'AFURLSessionManager -uploadTaskWithRequest:fromFile:progress:completionHandler:`,或者将其内容读取到分配给请求的'HTTPBody'属性的'NSData'。
 */
- (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request
                             writingStreamContentsToFile:(NSURL *)fileURL
                                       completionHandler:(nullable void (^)(NSError * _Nullable error))handler;

@end

pragma mark - AFMultipartFormData协议

/**
AFMultipartFormData 协议定义了支持`AFHTTPRequestSerializer -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:`方法中block参数中的参数.
 */
@protocol AFMultipartFormData

/**
通过文件路径(fileURL)的编码文件数据来拼接请求头参数`Content-Disposition: file; filename=#{generated filename}; name=#{name}"` and `Content-Type: #{generated mimeType}`

表单中此数据的文件名和MIME类型将分别使用'fileURL'的最后一个路径和系统关联MIME类型的'fileURL'扩展名自动生成。

MIME  (Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型(多媒体类型)
 */
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
                         name:(NSString *)name
                        error:(NSError * _Nullable __autoreleasing *)error;

/**
和上一个方法一样,不过要多传一个mineType作为文件数据的类型
 */
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
                         name:(NSString *)name
                     fileName:(NSString *)fileName
                     mimeType:(NSString *)mimeType
                        error:(NSError * _Nullable __autoreleasing *)error;

/**
拼接请求头参数`Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`
根据输入流和多部分表单边界数据拼接请求头参数。
length为输入流的长度
 */
- (void)appendPartWithInputStream:(nullable NSInputStream *)inputStream
                             name:(NSString *)name
                         fileName:(NSString *)fileName
                           length:(int64_t)length
                         mimeType:(NSString *)mimeType;

/**
 拼接请求头参数`Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`
根据文件数据和多部分表单边界数据。
 */
- (void)appendPartWithFileData:(NSData *)data
                          name:(NSString *)name
                      fileName:(NSString *)fileName
                      mimeType:(NSString *)mimeType;

/**
根据编码数据和多部分表单数据拼接请求头参数
`Content-Disposition: form-data; name=#{name}"`
 */

- (void)appendPartWithFormData:(NSData *)data
                          name:(NSString *)name;


/**
    拼接请求头根据编码数据和多部分表单边界
 */
- (void)appendPartWithHeaders:(nullable NSDictionary <NSString *, NSString *> *)headers
                         body:(NSData *)body;

/**
    通过限制包大小和为从上传流读取的每个块添加延迟来限制请求带宽。

     当通过3G或者 EDGE (Enhanced Data Rate for GSM Evolution)增强型数据速率GSM演进技术连接时,请求可能会失败,并显示“请求正文流已耗尽”。设置最大数据包大小和延迟可以降低输入流超出其分配带宽的风险。不幸的是,没有明确的方法来区分3G、EDGE或LTE连接与“ NSURLConnection”之间的区别。因此,不建议仅基于网络可访问性限制带宽。相反,您应该考虑检查故障块中的“请求正文流是否已耗尽”,然后重试用受限带宽进行请求。

 */
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
                                  delay:(NSTimeInterval)delay;

@end

pragma mark -AFJSONRequestSerializer

/**
 `AFJSONRequestSerializer` 是`AFHTTPRequestSerializer` 的子类,用来对参数通过用`NSJSONSerialization`进行JSON编码 ,设置请求的`Content-Type`编码方式为`application/json`
 */
@interface AFJSONRequestSerializer : AFHTTPRequestSerializer

/**
用于从Foundation对象写入请求JSON数据选项
 有关可能的值,请参阅“NSJsonSerialization”文档部分“ NSJSONWritingOptions”。默认为0
 */
@property (nonatomic, assign) NSJSONWritingOptions writingOptions;

/**
 创建并返回具有指定读写选项的JSON序列化对象。
 */
+ (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions;

@end

pragma mark -AFPropertyListRequestSerializer

/**
 `AFPropertyListRequestSerializer`是`AFHTTPRequestSerializer` 的子类,用`NSPropertyListSerializer`对惨呼进行JSON编码,设置请求的`Content-Type` 编码方式为`application/x-plist`.
 */
@interface AFPropertyListRequestSerializer : AFHTTPRequestSerializer

/**
属性列吧格式 可能的值可以参考"NSPropertyListFormat"
 */
@property (nonatomic, assign) NSPropertyListFormat format;

/**
 @warning The `writeOptions` property is currently unused.
这个属性当前没有使用
 */
@property (nonatomic, assign) NSPropertyListWriteOptions writeOptions;

/**
创建并返回一个带读写选项的属性序列化对象
 */
+ (instancetype)serializerWithFormat:(NSPropertyListFormat)format
                        writeOptions:(NSPropertyListWriteOptions)writeOptions;

@end

pragma mark -

///----------------
/// @name Constants
///----------------

/**

Error Domains

错误域定义了一些错误信息相关的静态变量

The following error domain is predefined.

Constants

AFURLRequestSerializationErrorDomain
AFURLRequestSerializer errors. Error codes for AFURLRequestSerializationErrorDomain correspond to codes in NSURLErrorDomain.
*/
FOUNDATION_EXPORT NSString * const AFURLRequestSerializationErrorDomain;

/**

User info dictionary keys

These keys may exist in the user info dictionary, in addition to those defined for NSError.

Constants

AFNetworkingOperationFailingURLRequestErrorKey
The corresponding value is an NSURLRequest containing the request of the operation associated with an error. This key is only present in the AFURLRequestSerializationErrorDomain.
*/
FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLRequestErrorKey;

/**

Throttling Bandwidth for HTTP Request Input Streams

@see -throttleBandwidthWithPacketSize:delay:

Constants

kAFUploadStream3GSuggestedPacketSize
Maximum packet size, in number of bytes. Equal to 16kb.

kAFUploadStream3GSuggestedDelay
Duration of delay each time a packet is read. Equal to 0.2 seconds.
*/
FOUNDATION_EXPORT NSUInteger const kAFUploadStream3GSuggestedPacketSize;
FOUNDATION_EXPORT NSTimeInterval const kAFUploadStream3GSuggestedDelay;

NS_ASSUME_NONNULL_END

上一篇 下一篇

猜你喜欢

热点阅读