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方法

results matching ""

    No results matching ""