RCTNetwork
RCTNetworking
sendRequest
入参
struct SpecSendRequestQuery {
NSString *method() const;
NSString *url() const;
id<NSObject> data() const;
id<NSObject> headers() const;
NSString *responseType() const;
bool incrementalUpdates() const;
double timeout() const;
bool withCredentials() const;
SpecSendRequestQuery(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
根据query构造NSMutableURLRequest,以下组装request
- withCredentials为true,则request的HTTPShouldHandleCookies为YES,这里会从sharedHTTPCookieStorage读取对应url的内容赋值给allHTTPHeaderFields
- headers,会把每一个项目调用addValue:forHTTPHeaderField:添加到header内
- data数据的解析,data是一个dictionary,data内有多个key,比如string、base64,最终赋值给HTTPBody
- string,从string解析出NSData的数据,return 返回key为body,value位NSData
- base64,解析出string,然后转换为NSData,然后return
- 如果Content-Encoding为gzip,会对HTTPBody进行gzip后再赋值
以下为发送request的过程
- 找到能够处理该request的RCTURLRequestHandler,遍历canHandleRequest来判断
- 通过request构造RCTNetworkTask,init 带上handler、request
- 调用task 的 start,这里会调用handler的sendRequest
RCTDataRequestHandler
进入的逻辑为scheme为data
实现构造一个NSBlockOperation,加入对应的NSOperationQueue,实现是直接调用 dataWithContentsOfURL
RCTFileRequestHandler
进入的逻辑为scheme为file
实现也是构造一个NSBlockOperation,加入对应的NSOperationQueue,实现是直接调用 dataWithContentsOfURL
RCTHTTPRequestHandler
进入的逻辑为scheme为http/https
实现:这里是调用NSURLSession的dataTaskWithRequest,通过NSMapTable来处理回调
XMLHTTPRequest
fetch是对XMLHTTPRequest的封装,XMLHTTPRequest实现如下
见send方法
- 监听native的相关网络回调方法,如didCompleteNetworkResponse
- 调用RCTNetworking的sendRequest方法
监听,这里会把返回的订阅者也保存
this._subscriptions.push(
RCTNetworking.addListener('didReceiveNetworkResponse', args =>
this.__didReceiveResponse(...args),
),
);
拦截器机制
XMLHTTPRequest可以调用setInterceptor,设置拦截器(XHRInterceptor),以收到网络请求各个阶段的消息
比如__didReceiveResponse就会调用interceptor的responseReceived方法
type XHRInterceptor = interface {
requestSent(id: number, url: string, method: string, headers: Object): void,
responseReceived(
id: number,
url: string,
status: number,
headers: Object,
): void,
dataReceived(id: number, data: string): void,
loadingFinished(id: number, encodedDataLength: number): void,
loadingFailed(id: number, error: string): void,
};
网络代理
见XHRInterceptor.js
这里hook了XMLHTTPRequest的请求相关方法,这个在RN的inspector开发者工具里用上了。可以拦截XMLHTTPRequest、fetch、以及其他依赖XMLHTTPRequest的请求库。
举例复写逻辑
XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
if (requestHeaderCallback) {
requestHeaderCallback(header, value, this);
}
originalXHRSetRequestHeader.apply(this, arguments);
};
send方法的复写逻辑
- 调用XHRInterceptor的sendCallback方法
- 调用XHR的addEventListener,增加readystatechange的监听,这里会callback 网络请求的当前状态
- 当HEADERS_RECEIVED,调用headerReceivedCallback
- 当为DONE时,调用responseCallback
- apply 原send方法