HarmonyOS —— Remote Communication Kit 拦截器(Interceptor)高阶定制能力笔记

这个就是 Remote Communication Kit 里“最能折腾”的一层:
配完 DNS / 传输 / 代理 / 安全 / 处理规则之后,再来一层 拦截器链,想怎么改请求/响应都行。


一、拦截器是什么?和前面的配置有什么不一样?

鸿蒙开发者第四期活动

之前你已经看了这些:

  • DnsConfiguration:改“怎么查 IP”
  • TransferConfiguration:改“超时/重试等传输策略”
  • ProxyConfiguration:改“走不走代理 & 用哪个代理”
  • SecurityConfiguration:改“证书、安全校验”
  • ProcessingConfiguration:改“怎么判定响应成功/失败”

拦截器(Interceptor)则是:

在整个 HTTP 请求/响应链路上,插入一串你自己写的“中间件”,
可以 读取 & 修改 Request / Response,还可以决定“放行 or 拦截”。

它的典型用途比 ProcessingConfiguration 更“野”:

  • 在请求发出去前:
    • 给所有请求加上统一 Header(如 Token、Trace-Id)
    • 动态改 URL、Host、Query、Body 等
  • 在响应回到业务前:
    • 统一处理/过滤/脱敏 Header
    • 在本地做缓存、Mock 返回
    • 打点、日志、A/B 实验埋点

ProcessingConfiguration 更像:

“我只看响应,帮你判断成功/失败。”

拦截器更像:

“我可以改请求、改响应,还能串成一个链,按顺序执行。”


二、设备 & 版本限制(老熟人)

和前面所有配置一样:

  • 支持设备:Phone / 2in1 / Tablet / Wearable
  • 5.1.1(19) 起:新增支持 TV

一句话背:

拦截器能力支持 Phone / 2in1 / Tablet / Wearable,5.1.1(19) 起新增 TV 支持


三、拦截器工作原理(链式执行)

文档里的示例设定了两个拦截器:

  • RequestUrlChangeInterceptor(下面叫:拦截器 1)
  • ResponseHeaderRemoveInterceptor(下面叫:拦截器 2)

请求方向:

  1. 应用代码发起请求 → 先进入拦截器 1
  2. 拦截器 1 可以改 URL(例如从 xxx.png 改成 xxx_small.png
  3. 再进入拦截器 2,可以继续改 Request
  4. 最后才真正发到 Internet/服务器

响应方向:

  1. 服务器返回 Response → 先被拦截器 2 截获
  2. 拦截器 2 可以改响应头、改响应体
  3. 再走到拦截器 1
  4. 最终才送到你的业务代码

顺序记忆:

  • 请求:按数组顺序执行(1 → 2 → … → 真正网络)
  • 响应:按逆序执行(… → 2 → 1 → 业务)

而且这些拦截器都是你自己通过类实现的:
实现 rcp.Interceptor 接口,在 intercept(context, next) 里编写逻辑


四、示例 1:根据网络质量动态改图片 URL

1. 模拟网络质量 — NetworkQualityProvider

export class NetworkQualityProvider {
  isNetworkFast: boolean = true

  public constructor(isNetworkFast: boolean) {
    this.isNetworkFast = isNetworkFast
  }
}

很简单:通过 isNetworkFast 来模拟网络好/差。
真实项目里,你可以用测速、信号强度、历史统计等来设置这个值。


2. RequestUrlChangeInterceptor:慢网改成“小图”

export class RequestUrlChangeInterceptor implements rcp.Interceptor {
  private readonly networkQualityProvider: NetworkQualityProvider;

  constructor(networkQualityProvider: NetworkQualityProvider) {
    this.networkQualityProvider = networkQualityProvider;
  }

  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    if (context.request.method === 'GET' && !this.networkQualityProvider.isNetworkFast) {
      console.info('[RequestUrlChangeInterceptor]: Slow network is detected');
      const parts = context.request.url.pathname.split('.');
      if (parts.length === 2) {
        const changed = url.URL.parseURL(context.request.url.href);
        changed.pathname = parts[0] + '_small.' + parts[1];
        console.info(`[RequestUrlChangeInterceptor]: Replace URL from "${context.request.url.href}" to "${changed}"`);
        AppStorage.setOrCreate('ReplacedInfo',
          `[RequestUrlChangeInterceptor]: Replace URL from "${context.request.url.href}" to "${changed}"`);
        context.request.url = changed;
      }
    } else {
      console.info('[RequestUrlChangeInterceptor]: Network is fast');
    }
    return next.handle(context);
  }
}

拆一下它在干嘛:

  1. 只处理 GET 请求,且网络不快时才介入:

    if (context.request.method === 'GET' && !this.networkQualityProvider.isNetworkFast) { ... }
    
  2. 拿到当前 URL 的 pathname,按 . 切开拿扩展名:

    • 比如 /images/banner.png['/images/banner', 'png']
  3. url.URL.parseURL 克隆出一个可变 URL 对象:

    const changed = url.URL.parseURL(context.request.url.href);
    changed.pathname = parts[0] + '_small.' + parts[1]; 
    // 变成 /images/banner_small.png
    
  4. 把替换信息写入 AppStorage(方便 UI 展示或调试)

  5. 将改好的 URL 回写:

    context.request.url = changed;
    
  6. 最后别忘了放行:

    return next.handle(context);
    

核心场景:
网络差时自动改用“小图 / 低清资源”,保证体验。


五、示例 2:ResponseHeaderRemoveInterceptor —— 过滤响应头

export class ResponseHeaderRemoveInterceptor implements rcp.Interceptor {
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    const response = await next.handle(context);
    const toReturn: rcp.Response = {
      request: response.request,
      statusCode: response.statusCode,
      httpVersion: response.httpVersion,
      headers: {
        'content-range': response.headers['content-range']
      },
      effectiveUrl: response.effectiveUrl,
      timeInfo: response.timeInfo,
      toJSON: () => null
    };
    console.info('[ResponseHeaderRemoveInterceptor]: Response was modified');
    return toReturn;
  }
}

做了两件事:

  1. 等下游(后面的拦截器 / 真正请求)返回 response

    const response = await next.handle(context);
    
  2. 构造一个新的 rcp.Response 对象:

    • 把原有的 request / statusCode / httpVersion / effectiveUrl / timeInfo 原样拷贝;

    • 只保留 content-range 这个响应头,其它 Header 都“清空”:

      headers: {
        'content-range': response.headers['content-range']
      },
      
  3. 记录日志,返回新的响应。

场景理解:
做一层统一的 Header 过滤 / 脱敏,比如在日志系统或下游模块只希望看到部分字段。


六、如何把拦截器挂到 Session 上?

拦截器是在 SessionConfiguration 里配置的:

function httpRequest(networkStateSimulator: NetworkQualityProvider) {
  const sessionConfig: rcp.SessionConfiguration = {
    interceptors: [
      new RequestUrlChangeInterceptor(networkStateSimulator),
      new ResponseHeaderRemoveInterceptor()
    ],
    requestConfiguration: {
      security: {
        tlsOptions: {
          tlsVersion: 'TlsV1.3'
        }
      }
    }
  };
  const session = rcp.createSession(sessionConfig);
}

关键点:

  • interceptors 是一个数组:
    • 前面的对“请求”先执行,对“响应”后执行(链式正向/反向)
  • 拦截器和其它配置(security.tlsOptions 等)可以一起用

你后续通过这个 session 发出的所有请求,都自动带上这两个拦截器。


七、你还可以用拦截器做什么?

几条你以后写博客/出题/实战可以用的思路:

  • 统一加 Header:
    • 比如每个请求自动带上 AuthorizationX-Trace-IdX-App-Version
  • 统一改 Host / Base URL:
    • 做灰度/多机房切换:写一个 EnvSwitchInterceptor 来动态决定请求真正打到哪里。
  • 本地 Mock:
    • 某些特定 URL,干脆不往网络发,直接在拦截器里返回一份假 rcp.Response
  • 重试 / 限流 / 熔断:
    • 在拦截器里检测响应错误码(如 5xx),决定是否再次 next.handle(context)
  • 日志 & 埋点:
    • 所有请求/响应统一在拦截器里打印或上报埋点。

八、最后给你一份“考点速记版”

  • 作用

    • 拦截并修改 HTTP 请求 & 响应,支持链式拦截器。
  • 核心接口

    interface Interceptor {
      intercept(context: RequestContext, next: RequestHandler): Promise<Response>;
    }
    
    • context.request:可读可改(URL、Header、Body 等)
    • next.handle(context):把请求传给下一个拦截器/网络层
    • Response:可重新构造后返回
  • 链路顺序

    • 请求:interceptors[0] → interceptors[1] → ... → 网络
    • 响应:网络 → ... → interceptors[1] → interceptors[0]
  • 设备支持

    • Phone / 2in1 / Tablet / Wearable
    • 自 5.1.1(19) 起支持 TV
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐