##鸿蒙核心技术##HarmonyOS SDK应用服务##RCP(远场通信)#

在上一篇文章中介绍了鸿蒙RCP远场通信的基本请求,https://blog.csdn.net/CZC2002/article/details/148195926?spm=1001.2014.3001.5501

在本文中,介绍RCP远场通信的拦截器的使用

1.拦截器的工作原理

    客户端发送HTTP请求,到达目标服务器之前,可以使用拦截器对HTTP的请求进行修改。如下图,定义了链式拦截器,RequestUrlChangeInterceptor拦截器(下文以拦截器1代替)和ResponseHeaderRemoveInterceptor拦截器(下文以拦截器2代替)。拦截器1会将请求先拦截,该拦截器可以实现当网络质量差时,通过修改HTTP请求中的URL,来调整请求资源的大小。然后经过拦截器2,最后到达Internet。当请求到达目标服务器,服务器返回请求响应的结果给客户端之前,可以使用拦截器对HTTP的响应进行修改。响应先被拦截器2拦截,在响应返回给应用前检查和修改服务器的请求头。然后经过拦截器1,最后客户端接收响应结果。

请求拦截器的实现(以get请求为例)

先用express写一个get接口

app.get('/api/persons', (req, res) => {
  if (req.headers["token"]) {
    if (req.headers["token"] == "1234") {
      res.status(200).json({
        code: 200,
        message: "请求成功",
        success: true,
        data: [{
          id: 1,
          name: "张三",
          age: 20
        }]
      })
    } else {
      res.status(601).json({
        code: 601,
        message: "认证信息有误",
        success: false
      })
    }
    res.status(600).json({
      code: 600,
      message: "请提供认证",
      success: false
    })
  }
})

那么get请求localhost:3000/api/persons这个路径,如果没有token则会收到请提供认证的响应,如果提供了token,但是不是1234那么会受到认证信息有误的响应,只有为1234才是正常的,

我们先写一个基础的请求拦截器

代码如下:

import { rcp } from "@kit.RemoteCommunicationKit";

class requestInterceptorClass {
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    if (context.request.method == "GET") {
      console.log("请求方法是get")
    }
    return next.handle(context);
  }
}

export const RequestInterceptor: rcp.SessionConfiguration = {
  interceptors: [
    new requestInterceptorClass()
  ],
  requestConfiguration: {}
}

在这里我们写了一个简单的请求拦截器,仅仅只对get'请求做了操作,然后如果是get则输出请求方式是get,现在让我们绑定到get中

回到我们的RCPPage文件中

修改rcpGet函数

  rcpGet = () => {
    const session = rcp.createSession(RequestInterceptor)
    session.get(rcpBaseUrl).then((res: rcp.Response) => {
      this.showList = (JSON.parse(JSON.stringify(res)) as getReturnModel).data
      console.log("res", JSON.stringify(res))
      session.close()
    }).catch((err: BusinessError) => {
      console.log("err", JSON.stringify(err))
    })
  }

在这里我们绑定了拦截器到session中

整个页面代码

import { rcp } from '@kit.RemoteCommunicationKit';
import { rcpBaseUrl } from '../rcpBaseUrl/rcpBaseUrl';
import { BusinessError } from '@kit.BasicServicesKit';
import { getReturnModel, GetReturnModelData } from '../Model/getReturnModel';
import { postBodyModel } from '../Model/postBodyModel';
import { putBodyModel } from '../Model/putBodyModel';
import { deleteBodyModel } from '../Model/deleteBodyModel';
import { RequestInterceptor } from '../Interceptor/RequestInterceptor';

@Entry
@Component
struct RCPGetPage {
  @State message: string = 'Hello World';
  @State showList: GetReturnModelData[] = []
  @State postName: string = ""
  @State putId:string=""
  @State putData:string=""
  @State deleteId:string=""
  rcpGet = () => {
    const session = rcp.createSession(RequestInterceptor)
    session.get(rcpBaseUrl).then((res: rcp.Response) => {
      this.showList = (JSON.parse(JSON.stringify(res)) as getReturnModel).data
      console.log("res", JSON.stringify(res))
      session.close()
    }).catch((err: BusinessError) => {
      console.log("err", JSON.stringify(err))
    })
  }
  rcpPost = (name: string) => {
    const session = rcp.createSession()
    session.post(rcpBaseUrl, { name } as postBodyModel).then((res: rcp.Response) => {
      console.log("res", JSON.stringify(res))
      session.close()
    }).catch((err: BusinessError) => {
      console.log("err", JSON.stringify(err))
    })
  }
  rcpPut=(data:putBodyModel)=>{
    const session=rcp.createSession()
    session.put(rcpBaseUrl,data).then((res: rcp.Response) => {
      console.log("res", JSON.stringify(res))
      session.close()
    }).catch((err: BusinessError) => {
      console.log("err", JSON.stringify(err))
    })
  }
  rcpDelete=(data?:deleteBodyModel)=>{
    const request = new rcp.Request(`${rcpBaseUrl}`, "DELETE", {
      "Content-Type": "application/json"
    }, data);
    const session=rcp.createSession()
    session.fetch(request).then((res: rcp.Response) => {
      console.log("header",JSON.stringify(res.headers))
      console.log("body",JSON.stringify(res.body))
      console.log("res", JSON.stringify(res))
      session.close()
    }).catch((err: BusinessError) => {
      console.log("err", JSON.stringify(err))
    })
}

  build() {
    Column() {
      Button("get请求")
        .onClick(() => {
          this.rcpGet()
        })
      ForEach(this.showList, (item: GetReturnModelData, index: number) => {
        Row() {
          Text("id")
          Blank().width(40)
          Text(item.id.toString())
          Blank().width(50)
          Text("name")
          Blank().width(40)
          Text(item.name)
        }
      }, (item: GetReturnModelData) => JSON.stringify(item))

      Divider().height(5).width("100%")
      TextInput({ placeholder: "请输入post的名字", text: $$this.postName })
      Button("post请求").onClick(() => {
        this.rcpPost(this.postName)
      })
      Divider().height(5).width("100%")
      TextInput({placeholder:"请输入put的id",text:$$this.putId})
      TextInput({placeholder:"请输入put的名字",text:$$this.putData})
      Button("put请求").onClick(()=>{
        this.rcpPut({id:this.putId,name:this.putData})
      })
      Divider().height(5).width("100%")
      TextInput({placeholder:"请输入删除的id",text:$$this.deleteId})
      Button("delete请求").onClick(()=>{
        this.rcpDelete({id:this.deleteId})
      })
    }
    .height('100%')
    .width('100%')
  }
}

现在我们之间点击get请求按钮,发现控制台输出:

符合我们的预期,现在我们修改拦截器

class requestInterceptorClass {
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    if (context.request.method == "GET") {
      context.request.headers={
        token:"12345"
      }
      console.log("请求方法是get")
    }
    return next.handle(context);
  }
}

我们提供token为12345,那么预期输出认证信息不对

我们再点击get按钮

符合我们的预期

那么再修改get请求为正确的

class requestInterceptorClass {
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    if (context.request.method == "GET") {
      context.request.headers={
        token:"1234"
      }
      console.log("请求方法是get")
    }
    return next.handle(context);
  }
}

那么就应该输出正常的

发现没问题,模拟器上也正常显示

除此之外,我们可以设置某些url不需要token

代码如下

import { rcp } from "@kit.RemoteCommunicationKit";

const urlArr: string[] = []

class requestInterceptorClass {
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    if (!urlArr.includes(context.request.url.toString())) {
      if (context.request.method == "GET") {
        context.request.headers = {
          token: "1234"
        }
        console.log("请求方法是get")
      }
    }
    return next.handle(context);
  }
}

export const RequestInterceptor: rcp.SessionConfiguration = {
  interceptors: [
    new requestInterceptorClass()
  ],
  requestConfiguration: {}
}

在定义的urlArr中的url则不添加token

响应拦截器

代码如下:

class responseInterceptorClass {
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    console.log("响应拦截器")
    const response = await next.handle(context)
    const toReturn: rcp.Response = {
      request: response.request,
      statusCode: response.statusCode,
      headers: {
        token: response.headers.token
      },
      toJSON: () => (response.toJSON())
    }
    console.log("code",toReturn.statusCode)
    if (toReturn.statusCode == 601) {
      AlertDialog.show({
        message: "认证信息有误"
      })
    }
    if (toReturn.statusCode == 600) {
      AlertDialog.show({
        message: "请气功认证信息"
      })
    }
    return toReturn
  }
}

其中,返回参数的request,statusCode,headers和toJson必传

现在我们修改config

export const RequestInterceptor: rcp.SessionConfiguration = {
  interceptors: [
    new requestInterceptorClass(),
    new responseInterceptorClass()
  ],
  requestConfiguration: {}
}

然后我们修改token为12345

那么会弹出一个认证信息有误的弹窗

点击get按钮

符合我们的预期

现在我们测试不给token,代码如下

class requestInterceptorClass implements rcp.Interceptor{
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    // if (!urlArr.includes(context.request.url.toString())) {
    if (context.request.method == "GET") {
      // context.request.headers = {
      //   // token: "1234"
      // }
      // context.request.headers!["token"]="12345"
      console.log("请求方法是get")
    }
    // }
    return next.handle(context);
  }
}

点击get按钮:

符合预期,也就是响应拦截器也配置完成

文件目录如下

D:.
│  .clang-format
│  .gitignore
│  build-profile.json5
│  code-linter.json5
│  hvigorfile.ts
│  local.properties
│  oh-package-lock.json5
│  oh-package.json5

├─.idea
│  │  .gitignore
│  │  modules.xml
│  │  workspace.xml
│  │
│  ├─.deveco
│  │  │  project.cache.json
│  │  │
│  │  └─module
│  │          entry.cache.json
│  │
│  └─modules
│      │  RCPMessage.iml
│      │
│      └─entry
│              entry.iml

├─AppScope
│  │  app.json5
│  │
│  └─resources
│      └─base
│          ├─element
│          │      string.json
│          │
│          └─media
│                  background.png
│                  foreground.png
│                  layered_image.json

├─entry
│  │  .gitignore
│  │  build-profile.json5
│  │  hvigorfile.ts
│  │  obfuscation-rules.txt
│  │  oh-package.json5
│  │
│  └─src
│      ├─main
│      │  │  module.json5
│      │  │
│      │  ├─ets
│      │  │  ├─entryability
│      │  │  │      EntryAbility.ets
│      │  │  │
│      │  │  ├─entrybackupability
│      │  │  │      EntryBackupAbility.ets
│      │  │  │
│      │  │  ├─Interceptor
│      │  │  │      RequestInterceptor.ets
│      │  │  │
│      │  │  ├─Model
│      │  │  │      deleteBodyModel.ets
│      │  │  │      getReturnModel.ets
│      │  │  │      postBodyModel.ets
│      │  │  │      putBodyModel.ets
│      │  │  │
│      │  │  ├─pages
│      │  │  │      Index.ets
│      │  │  │      RCPPage.ets
│      │  │  │
│      │  │  └─rcpBaseUrl
│      │  │          rcpBaseUrl.ets
│      │  │
│      │  └─resources
│      │      ├─base
│      │      │  ├─element
│      │      │  │      color.json
│      │      │  │      float.json
│      │      │  │      string.json
│      │      │  │
│      │      │  ├─media
│      │      │  │      background.png
│      │      │  │      foreground.png
│      │      │  │      layered_image.json
│      │      │  │      startIcon.png
│      │      │  │
│      │      │  └─profile
│      │      │          backup_config.json
│      │      │          main_pages.json
│      │      │
│      │      ├─dark
│      │      │  └─element
│      │      │          color.json
│      │      │
│      │      └─rawfile
│      ├─mock
│      │      mock-config.json5
│      │
│      ├─ohosTest
│      │  │  module.json5
│      │  │
│      │  └─ets
│      │      └─test
│      │              Ability.test.ets
│      │              List.test.ets
│      │
│      └─test
│              List.test.ets
│              LocalUnit.test.ets

└─hvigor
        hvigor-config.json5
 

最后,拦截器的总体代码如下:

import { rcp } from "@kit.RemoteCommunicationKit";

const urlArr: string[] = []

class requestInterceptorClass implements rcp.Interceptor{
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    // if (!urlArr.includes(context.request.url.toString())) {
    if (context.request.method == "GET") {
      // context.request.headers = {
      //   // token: "1234"
      // }
      // context.request.headers!["token"]="12345"
      console.log("请求方法是get")
    }
    // }
    return next.handle(context);
  }
}

interface test {
  message: string
}

class responseInterceptorClass implements rcp.Interceptor{
  async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {
    console.log("响应拦截器")
    const response = await next.handle(context)
    console.log("response",JSON.stringify(response),JSON.stringify(response.toJSON()))
    console.log("header",JSON.stringify(response.headers))
    const toReturn: rcp.Response = {
      request: response.request,
      statusCode: response.statusCode,
      headers: Object.keys(response.headers).length ? response.headers : {},
      toJSON: () => (response.toJSON())
    }
    console.log("code", toReturn.statusCode)
    if (toReturn.statusCode == 601) {
      AlertDialog.show({
        message: "认证信息有误"
      })
    }
    if (toReturn.statusCode == 600) {
      AlertDialog.show({
        message: "请气功认证信息"
      })
    }
    return toReturn
  }
}

export const RequestInterceptor: rcp.SessionConfiguration = {
  interceptors: [
    new requestInterceptorClass(),
    new responseInterceptorClass()
  ],
  requestConfiguration: {}
}

Logo

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

更多推荐