18 接口自动化 接口管理模块开发(七)

别人写的平台再垃圾,也是用来淘汰你的。

Python环境没有的,请自行安装,本教程采用的是python 3.9。

Django官网 https://www.djangoproject.com/

Node环境没有的,请自行安装,本教程采用的是node v17.6.0。

Vue.js官网 https://cn.vuejs.org/

接着上章,本章将完成接口的调试功能。

接口管理模块开发(七)

环境管理主要逻辑

上章完成的新增功能中可以看到接口只保存了路径,没有域名端口等信息,大概的设想是将其保存在环境信息中,选择不同的环境请求不同的IP/域名、端口。

因此在完成接口调试功能前先完成「环境管理」的增删改查功能,因为没有复杂的业务处理,可以查看前面的「项目管理模块开发」系列,这里不再进行详细介绍,主要步骤如下:

  • 在后端项目中定义Model类,然后使用DRF的ModelViewSet快速定义接口,最后设置路由

  • 在前端项目中新增页面,并且新增路由指向新页面,然后在新页面上使用Table组件进行数据展示;定义增删改查接口,并在相应的按钮事件中进行调用。

接口调试功能

环境管理功能开发完成后,就可以开始进行接口调试功能开发了。主要交互如下:

  • 新增下拉框用于选择环境
  • 选择环境后,点击接口信息右侧的【Send】按钮,将环境信息和当前页面的接口信息通过接口传给后端接口
  • 后端接口中根据环境信息和接口信息进行处理后,使用requests模块访问接口
  • 将接口返回的信息进行封装,按照「完整请求」、「响应内容」、「响应头」三部分进行返回

后端接口定义

  • 首先后端自定义一个ApiSendView继承APIView,然后定义一个post方法用来提供一个post类型的接口。
  • 因为接口信息跟接口保存的参数一致,可以使用ApiSerializer进行解析。而环境信息需要单独从请求体中获取。
class ApiSendView(APIView):
    def post(self, request):
        api = ApiSerializer(request.data).instance
        env = ''
        if 'env' in request.data:
            env = request.data['env']
  • 因为要使用requests模块来发送请求,因此需要先安装requests(参考前面章节,不再赘述),安装完成后,在项目目录下新增一个utils目录存放项目用到的工具,然后在utils下新增一个request_util.py文件,专门用来处理请求,新增方法用来拼接请求参数和处理响应数据,具体代码如下。
def request_by_api(env: Env, api: Dict) -> Response:
    return request_by_domain(domain=env.domain,
                             protocol=env.protocol,
                             port=env.port,
                             path=api["path"],
                             params=api["params"],
                             body=api["body"],
                             body_type=api["body_type"],
                             headers=api["headers"],
                             method=api["method"]
                             )


def request_by_domain(
        domain: str,
        port: str,
        path: str,
        params: str,
        body: str,
        headers: str,
        protocol: str = "HTTP",
        body_type: str = "NONE",
        method: str = "GET") -> Response:
    url = f"{
      
      protocol.lower()}://{
      
      domain}"
    if port:
        url += f":{
      
      port}"
    url += path
    req_params = {
    
    }
    if len(params) > 0:
        for param in params:
            req_params[param['param_key']] = param['value']
    req_headers = {
    
    }
    if len(headers) > 0:
        for header in headers:
            req_headers[header['param_key']] = header['value']
    if method == "GET":
        return request(method, url, headers=req_headers, params=req_params)
    else:
        if body_type == "JSON":
            return request(method=method, url=url, params=params, headers=headers, json=body)
        else:
            return request(method=method, url=url, params=params, headers=headers, data=body)


def response_handler(resp:Response):
    # 进行请求封装
    result = {
    
    
        "body": resp.content,
        "headers": resp.headers,
        "content": 
        f"""{
      
      resp.request.method} {
      
      resp.request.url} {
      
      resp.status_code}
请求头:{
      
      resp.request.headers}
请求体:{
      
      resp.request.body}"""
    }
    return result

  • 接着在新接口中使用工具类进行请求和响应的处理,如下:
class ApiSendView(APIView):
    def post(self, request):
        api = ApiSerializer(request.data).instance
        env = ''
        if 'env' in request.data:
            env = request.data['env']
        env = Env.objects.get(id=env)
        resp = request_util.request_by_api(env, api)
        return Response(request_util.response_handler(resp))

到这里接口就处理完毕了,接下来完成前端的交互。

前端页面交互

首先新增下拉框展示所有的环境信息,效果如下图:

  • 新增变量保存环境列表数据,在onMounted方法中调用接口查询环境列表。
const envs = ref([]);
onMounted(() => {
    
    
  listApi().then((res) => {
    
    
    envs.value = res;
  });
});
  • 然后在select组件中展示所有的环境信息。
<a-select placeholder="请选择环境">
  <a-select-option v-for="env in envs" :key="env.id" :value="env.id">{
   
   {
    env.name
  }}</a-select-option>
</a-select>
  • 最终效果如下:

然后给【Send】按钮添加点击事件,将环境信息和当前填写的接口信息作为接口参数。

import {
    
    addApiApi, apiSendApi} from "../../apis/api";

const sendApi = () => {
    
    
  // 获取请求体
  if (apiBodyRef.value) {
    
    
    formState.value.body_type = apiBodyRef.value.body_type;
    formState.value.body = apiBodyRef.value.getData();
    if (formState.value.body === "") {
    
    
      formState.value.body_type = "NONE";
    }
  }
  // 测试环境
  if (enviroment.value) {
    
    
    formState.value.env = enviroment.value;
  }
  apiSendApi(formState.value).then((res) => {
    
    
    console.log(res);
  });
};

重启项目,刷新页面,选择环境后进行接口调试,可以看到控制台成功输出响应信息。接下来就是将响应信息中的响应体、响应头、请求内容展示在对应的tab中。

前端结构优化(状态管理)

在获取响应数据之前,先来对前端结构进行优化,避免组件之前传值过程过于复杂。


首先来看下当前ApiListView页面存在问题,为了防止ApiListView页面功能过多导致文件过大,因此对不同的部分进行了组件拆分,随之而来的是组件之前传值的问题。

  • 例如接口详情,首先在ApiListSider组件中获取到接口ID,然后传递到父组件ApiListView,再由父组件ApiListView传递给子组件ApiContent,接着再将请求参数传递给子组件ApiParams,最后传递给TableForm用于展示。其他字段,比如请求头、请求体也是如此,操作链路非常长。
  • 例如接口调试获得了响应信息,首先在ApiListSider组件中获取到响应信息,将响应头给子组件resBody,然后传递给Coder,其他字段,比如响应头,请求内容也是如此。

上诉问题有两个解决方案:
1、将子组件引用链缩短,例如ApiListContent直接使用TableForm展示请求头信息,去掉ApiParams组件。其他字段也是如此。
2、使用pinia进行状态管理,这样状态信息就不再需要在组件链上传递,只需要在要使用时访问状态即可。

因为使用脚手架搭建项目框架已经选择安装了pinia依赖,所以无需安装(没有的,请自行进行安装)。

按接口调试的响应信息举例:

  • 首先在前端项目src/stores下新增api.js文件用来存放接口管理相关的状态。
import {
    
     ref } from "vue";
import {
    
     defineStore } from "pinia";

export const useApiResponseStore = defineStore("apiResponse", () => {
    
    
  const resBody = ref("");
  const resHeaders = ref([]);
  const reqContent = ref("");
  const updateResponse = (data) => {
    
    
    resBody.value = data["body"];
    resHeaders.value = data["headers"];
    reqContent.value = data["content"];
  };

  return {
    
     resBody, resHeaders, reqContent, updateResponse };
});
  • 在组件ApiListView中直接调用updateReponse方法更新响应信息。
const apiResponse = useApiResponseStore();
const sendApi = () => {
    
    
  ...
  apiSendApi(formState.value).then((res) => {
    
    
    apiResponse.updateResponse(res);
  });
};
  • 在组件ResBody中直接使用apiResponse.resBody获取保存的状态信息
<template>
  <div class="res-body">
    <api-coder
      :lang="'json'"
      :initHeight="'250px'"
      :content="apiResponse.resBody"
      @updateScript="updateContent"
    ></api-coder>
  </div>
</template>

<script setup>
import ApiCoder from "@/components/ApiCoder.vue";
import {
      
       useApiResponseStore } from "../../stores/api";

const apiResponse = useApiResponseStore();

const updateContent = (content) => {
      
      
  apiResponse.resBody = content;
};
</script>

重启项目,刷新页面,再次选择环境后,进行接口调试功能,可以看到resBody可以正常展示响应数据了,如下图:

响应头和请求内容也是按照上面的步骤进行处理,从状态中直接获取信息,不再进行组件之间数据的传递,实现后效果如下。

篇幅有限,接口调试功能就结束啦,前面使用通过组件间传递的信息都可以使用状态管理进行改造,大家可自行进行修改。下节将继续接口的增删改查功能,敬请期待~

猜你喜欢

转载自blog.csdn.net/ahu965/article/details/127180196