18 Development of Interface Automation Interface Management Module (7)

No matter how rubbish the platform written by others is, it is also used to eliminate you.

If there is no Python environment, please install it yourself. This tutorial uses python 3.9.

Django official website https://www.djangoproject.com/

If there is no Node environment, please install it yourself. This tutorial uses node v17.6.0.

Vue.js official website https://cn.vuejs.org/

Following the last chapter, this chapter will complete the debugging function of the interface.

Interface management module development (7)

The main logic of environmental management

From the new functions completed in the previous chapter, you can see that the interface only saves the path, without information such as the domain name and port. The general idea is to save it in the environment information, and select different environments to request different IP/domain names and ports.

Therefore, before completing the interface debugging function, first complete the addition, deletion, modification and query function of "Environment Management". Because there is no complicated business processing, you can refer to the previous "Project Management Module Development" series, which will not be described in detail here. The main steps are as follows:

  • Define the Model class in the backend project, then use DRF's ModelViewSetquick definition interface, and finally set the route

  • Add a new page in the front-end project, and add a new route to point to the new page, and then use the Table component on the new page to display data; define the interface for addition, deletion, modification, and query, and call it in the corresponding button event.

Interface debugging function

After the development of the environment management function is completed, the development of the interface debugging function can be started. The main interactions are as follows:

  • Added a drop-down box for selecting the environment
  • After selecting the environment, click the [Send] button on the right side of the interface information to send the environment information and the interface information of the current page to the backend interface through the interface
  • After processing according to the environment information and interface information in the back-end interface, use requeststhe module to access the interface
  • Encapsulate the information returned by the interface and return it in three parts: "full request", "response content", and "response header"

Backend interface definition

  • First, the backend defines an ApiSendViewinheritance APIView, and then defines a post method to provide a post type interface.
  • Because the interface information is consistent with the parameters saved in the interface, ApiSerializer can be used for analysis. The environment information needs to be obtained separately from the request body.
class ApiSendView(APIView):
    def post(self, request):
        api = ApiSerializer(request.data).instance
        env = ''
        if 'env' in request.data:
            env = request.data['env']
  • Because you need to use requeststhe module to send requests, you need to install it first requests(refer to the previous chapters, no more details). After the installation is complete, add a directory under the project directory utilsto store the tools used in the project, and utilsthen add a request_util.pynew file below, specifically It is used to process requests, and the new method is used to splice request parameters and process response data. The specific code is as follows.
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

  • Then use the tool class in the new interface to process the request and response, as follows:
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))

At this point, the interface is processed, and then the front-end interaction is completed.

Front-end page interaction

First, add a drop-down box to display all the environment information, the effect is as follows:

  • A new variable is added to save the environment list data, and onMountedthe interface is called in the method to query the environment list.
const envs = ref([]);
onMounted(() => {
    
    
  listApi().then((res) => {
    
    
    envs.value = res;
  });
});
  • Then selectdisplay all the environment information in the component.
<a-select placeholder="请选择环境">
  <a-select-option v-for="env in envs" :key="env.id" :value="env.id">{
   
   {
    env.name
  }}</a-select-option>
</a-select>
  • The final effect is as follows:

Then add a click event to the [Send] button, and use the environment information and the currently filled interface information as interface parameters.

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);
  });
};

Restart the project, refresh the page, select the environment and perform interface debugging, and you can see that the console successfully outputs response information. The next step is to display the response body, response header, and request content in the response information in the corresponding tab.

Front-end structure optimization (state management)

Before getting the response data, first optimize the front-end structure to avoid the complicated process of passing values ​​before components.


First of all, let’s look at the current problems of the ApiListView page. In order to prevent the ApiListView page from having too many functions and causing the file to be too large, the components are split into different parts, followed by the problem of passing values ​​before the components.

  • For example, for interface details, first ApiListSiderobtain the interface ID in the component, then pass it to the parent component ApiListView, then the parent component ApiListViewpasses it to the child component ApiContent, then pass the request parameters to the child component ApiParams, and finally pass it to TableFormthe display. The same is true for other fields, such as request headers and request bodies, and the operation link is very long.
  • For example, if the interface debugging obtains the response information, first ApiListSiderobtain the response information in the component, pass the response header to the subcomponent resBody, and then pass it Coderto other fields, such as the response header, and the request content is the same.

There are two solutions to the appeal problem:
1. Shorten the sub-component reference chain, for example, ApiListContent directly uses TableForm to display the request header information, and removes the ApiParams component. The same goes for other fields.
2. Use piniafor state management, so that state information no longer needs to be passed on the component chain, and you only need to access the state when you want to use it.

Because the project framework has been installed with scaffolding pinia, there is no need to install it (if not, please install it yourself).

Example of response information for debugging by interface:

  • src/storesFirst, add a new file under the front-end project api.jsto store the state related to interface management.
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 };
});
  • ApiListViewCall the method directly in the component updateReponseto update the response information.
const apiResponse = useApiResponseStore();
const sendApi = () => {
    
    
  ...
  apiSendApi(formState.value).then((res) => {
    
    
    apiResponse.updateResponse(res);
  });
};
  • ResBodyUse directly in the component apiResponse.resBodyto get the saved state information
<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>

Restart the project, refresh the page, select the environment again, and perform the interface debugging function. You can see that resBody can display the response data normally, as shown in the figure below:

The response header and request content are also processed according to the above steps, and the information is obtained directly from the state, and the data transfer between components is no longer performed. The effect after implementation is as follows.

The space is limited, and the interface debugging function is over. The information passed between components used earlier can be modified using state management, and you can modify it yourself. The next section will continue to add, delete, modify and query the interface, so stay tuned~

Guess you like

Origin blog.csdn.net/ahu965/article/details/127180196