Hongmeng development practice: network request library [axios]

Introduction

[Axios] ,is a based on promise network request library,Can run node.js and in the browser。This library is based on[Axios]original libraryv1.3.4version to adapt,so that it can be run on OpenHarmony,and inherit its existing usage and features。

  • http ask
  • Promise API
  • request and response Interceptor
  • Convert request and response of data data
  • automatic conversion JSON data data

Download and install

ohpm install @ohos/axios 

Permission required

ohos.permission.INTERNET 

Interface and property list

interface list

interface parameter Function
axios(config) [config]:Request configuration send request
axios.create(config) [config]:Request configuration Create instance
axios.request(config) [config]:Request configuration send request
axios.get(url[, config]) url:Request address [config]:Request configuration sendgetask
axios.delete(url[, config]) url:Request address [config]:Request configuration senddeleteask
axios.post(url[, data[, config]]) url:Request address data:Send request body data [config]:Request configuration sendpostask
axios.put(url[, data[, config]]) url:Request address data:Send request body data [config]:Request configuration sendputask

Property list

Attributes describe
axios.defaults[‘xxx’] default setting 。The value is the request configuration [config] Configuration items in For example axios.defaults.headers Get header information
axios.interceptors Interceptor。reference [Interceptor] usage of

Usage example

before use indemomiddleentry–>src–>main–>ets–>common–>Common.etsChange the file to the correct server address,existentry–>src–>main–>resources–>rawfileAdd the correct certificate to the directory,can be used normallydemo。

initiate a GET ask

axiosSupports generic parameters,becauseArkTSNo longer supportedanytype,The specific type of the parameter needs to be specified。 like:axios.get(url)

  • T: is the response data type。When sending a POST when requested,The client may receive a JSON object。T This is it JSON object type。by default,T yes any,This means that any type of data can be received。
  • R: Is the type of response body。When the server returns a response,The response body is usually a JSON object。R This is it JSON object type。by default,R yes AxiosResponse,This means that the response body is a AxiosResponse object,its data The properties are T Type of
  • D: Is the type of request parameter。When sending a GET when requested,may be in URL Add some query parameters in。D These are the types of query parameters。When the parameter is empty,D yes nulltype。
import axios from '@ohos/axios'
interface userInfo{
  id: number
  name: string,
  phone: number
}

// towards the givenIDof users initiated requests
axios.get<userInfo, AxiosResponse<userInfo>, null>('/user?ID=12345')
.then((response: AxiosResponse<userInfo>)=> {
  // Handle success situations
  console.info("id" + response.data.id)
  console.info(JSON.stringify(response));
})
.catch((error: AxiosError)=> {
  // Handle error conditions
  console.info(JSON.stringify(error));
})
.then(()=> {
  // will always be executed
});

// The above request can also be done as follows(Optional)
axios.get<userInfo, AxiosResponse<userInfo>, null>('/user', {
  params: {
    ID: 12345
  }
})
.then((response:AxiosResponse<userInfo>) => {
  console.info("id" + response.data.id)
  console.info(JSON.stringify(response));
})
.catch((error:AxiosError) => {
  console.info(JSON.stringify(error));
})
.then(() => {
  // will always be executed
});

// supportasync/awaitusage
async function getUser() {
  try {
        const response:AxiosResponse = await axios.get<string, AxiosResponse<string>, null>(this.getUrl);
        console.log(JSON.stringify(response));
      } catch (error) {
    console.error(JSON.stringify(error));
  }
} 

send a POST ask

interface user {
  firstName: string,
  lastName: string
}
   axios.post<string, AxiosResponse<string>, user>('/user', {
     firstName: 'Fred',
     lastName: 'Flintstone'
   })
   .then((response: AxiosResponse<string>) => {
     console.info(JSON.stringify(response));
   })
   .catch((error) => {
  console.info(JSON.stringify(error));
}); 

Initiate multiple concurrent requests

 const getUserAccount = ():Promise<AxiosResponse> => {
      return axios.get<string, AxiosResponse<string>, null>('/user/12345');
    }

 const getUserPermissions = ():Promise<AxiosResponse> => {
      return axios.get<string, AxiosResponse<string>, null>('/user/12345/permissions');
    }

 Promise.all<AxiosResponse>([getUserAccount(), getUserPermissions()])
 .then((results:AxiosResponse[]) => {
        const acct = results[0].data as string;
        const perm = results[1].data as string;
      }); 

Instructions for use

axios API

by axios Pass relevant configuration to create the request
axios(config)
// send agetask
axios<string, AxiosResponse<string>, null>({
  method: "get",
  url: 'https://www.xxx.com/info'
}).then((res: AxiosResponse) => {
  console.info('result:' + JSON.stringify(res.data));
}).catch((error: AxiosError) => {
  console.error(error.message);
}) 
axios(url[, config])
// send agetask(Default request method)
axios.get<string, AxiosResponse<string>, null>('https://www.xxx.com/info', { params: { key: "value" } })
.then((response: AxiosResponse) => {
  console.info("result:" + JSON.stringify(response.data));
})
.catch((error: AxiosError) => {
  console.error("result:" + error.message);
}); 
request method Alias ​​mode to create a request

for your convenience,Aliases are provided for all supported request methods。

  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])

Notice: When using alias methods, url、method、data None of these properties have to be specified in the configuration。

// sendgetask
axios.get<string, AxiosResponse<string>, null>('https://www.xxx.com/info', { params: { key: "value" } })
.then((response: AxiosResponse) => {
  console.info("result:" + JSON.stringify(response.data));
})
.catch((error: AxiosError) => {
  console.error("result:" + error.message);
}); 

axios Example

Create an instance

You can create a new instance with a custom configuration。
axios.create([config])

const instance = axios.create({
  baseURL: 'https://www.xxx.com/info',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
}); 
instance method
  • axios#request(config)
  • axios#get(url[, config])
  • axios#delete(url[, config])
  • axios#post(url[, data[, config]])
  • axios#put(url[, data[, config]])

)Request configuration

These are the configuration options available when creating a request。only url is compulsory。if not specified method,Requests will default to using get method。

{
  // `url` is the server used for requests URL
  url: '/user',

  // `method` is the method used when creating a request supportpost/get/put/deletemethod,not case sensitive,The default isgetmethod
  method: 'get', // default

  // `baseURL` will be automatically added to `url` Front,unless `url` is an absolute URL。
  // It can be done by setting a `baseURL` Convenient for axios Instance method passing relative URL
  baseURL: 'https://www.xxx.com/info',

  // `transformRequest` Allow before sending to server,Modify request data
  // it can only be used 'PUT', 'POST' and 'PATCH' These request methods
  // The last function in the array must return a string, oneBufferExample,ArrayBuffer,FormData,or Stream
  // You can modify the request headers。
  transformRequest: [function (data, headers) {
    // to sent data Perform any conversion processing
    return data;
  }],

  // `transformResponse` passing to then/catch forward,Allow modification of response data
  transformResponse: [function (data) {
    // to receiving data Perform any conversion processing
    return data;
  }],

  // `headers` Is the custom request header that will be sent
  headers: {'Content-Type': 'application/json'},

  // `params` is to be sent with the request URL parameter
  // Must be a plain object(plain object),Other objects such as URLSearchParams ,must use paramsSerializer serialize
  params: {
    ID: 12345
  },

  // `paramsSerializer` is a responsible `params` serialized function
  paramsSerializer: function(params) {
    return params
  },

  // `data` is the data sent as the body of the request
  // Applies only to these request methods 'PUT', 'POST', and 'PATCH'
  // In no setting `transformRequest` hour,Must be one of the following types,Other types of use transformRequest Conversion processing
  // - string, plain object, ArrayBuffer
  data: {
    firstName: 'Fred'
  },

  // Optional syntax for sending request body data
  // Request method post
  // only value will be sent,key will not
  data: 'Country=Brasil&City=Belo Horizonte',

  // `timeout` Specifies the number of milliseconds for request timeout(0 Indicates no timeout period)
  // If the request exceeds `timeout` time,The request will be interrupted
  timeout: 1000,

  // `adapter` Allow custom handling of requests,This makes testing easier。
  // Return a promise and provide a valid response (See lib/adapters/README.md)。
  adapter: function (config) {
    /* ... */
  },
  // If this parameter is set,The system will use the user-specified pathCACertificate,(Developers need to ensure that this pathCACertificate accessibility),Otherwise the system default will be usedCACertificate,System defaultCACertificate location:/etc/ssl/certs/cacert.pem。The certificate path is the sandbox mapping path(Developers can useGlobal.getContext().filesDirGet application sandbox path)。
  caPath: '',

  // client certificateclientCertField,include4attributes:
  // client certificate(cert)、Client certificate type(certType)、Certificate private key(key)and passphrase(keyPasswd)。
  clientCert:{
      certPath: '',  // Client certificate path
      certType: '',  // Client certificate type,includepem、der、p12three kinds
      keyPath: '',   // Certificate private key path
      keyPasswd: ''  // passphrase
  }

  // priority,scope[1,1000],The default is1,The larger the value,The higher the priority;
  priority: 1,

  //  `responseType` Specify the type of return data,This field is not available by default。If this parameter is set,The system will give priority to returning the specified type。
  // Options include: string:string type; object:Object type; array_buffer:binary array type。
  responseType: 'string', 

  //  `proxy`
  // use or notHTTPacting,The default isfalse,Not using a proxy。
  // whenproxyforAxiosProxyConfigtype,Use specified network proxy。
  proxy: {
      host: 'xx', // Host port
      port: xx, // Host port
      exclusionList: [] // Do not use a blocking list for proxy servers
  }

  // `onUploadProgress` Allow handling of progress events for uploads
  onUploadProgress: function (progressEvent) {
    // Handling native progress events
  },

  // `onDownloadProgress` Allow handling of progress events for downloads,This event must be set to download files
  onDownloadProgress: function (progressEvent) {
    // Handling native progress events
  },

  // Application-based context,Applies to upload only/Download request
  context: context,

  // Download path。This parameter,Applies only to download requests,
  // StageUsed under the modelAbilityContext Class gets file path,for example:'${getContext(this).cacheDir}/test.txt’and store the file under this path
  filePath: context,
  } 

response structure

The response to a request contains the following information。

{
  // `data` response provided by the server
  data: {},

  // `status` response from server HTTP status code
  status: 200,

  // `statusText` response from server HTTP status information
  statusText: 'OK',

  // `headers` Is the server response header
  // all header Names are all lowercase,And can be accessed using square bracket syntax
  // For example: `response.headers['content-type']`
  headers: {},

  // `config` yes `axios` Requested configuration information
  config: {},

  // `request` is the request that generated this response
  request: {}
} 

when using then hour,You will receive a response like this:

axios.get<string, AxiosResponse<string>, null>(this.getUrl)
 .then( (response:AxiosResponse<string>)=> {
   console.log("result data: " + response.data);
   console.log("result status: " + response.status);
   console.log("result statusText: " + response.statusText);
   console.log("result headers: " + response.headers);
   console.log("result config: " + response.config);
 }); 

default allocation

You can specify a default configuration,It will be applied to every request。

overall situation axios default value
axios.defaults.baseURL = 'https://www.xxx.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 
Custom instance default values
// Configure default values ​​when creating an instance
const instance = axios.create({
  baseURL: 'https://www.xxx.com'
});

// Modify the default value after creating the instance
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN; 

Configured priority Configurations will be merged according to priority。Its order is:existlib/defaults.jsLibrary defaults found in,Then there are examples defaults Attributes,Finally it was requested config parameter。The later ones have higher priority than the earlier ones.。Here is an example。

// Create an instance using the default configuration provided by the library
// The default value for the timeout configuration at this time is `0`
const instance = axios.create();

// Override the library&#39;s timeout defaults
// Now,All requests using this instance will wait2.5Second,Then it will time out
instance.defaults.timeout = 2500;

// Override the timeout for this request,Because the request takes a long time
instance.get<string, AxiosResponse<string>, null>(this.getUrl, {
  timeout: 5000
}) 

Interceptor

The request or response is then or catch intercept them before processing。

// Add request interceptor
axios.interceptors.request.use((config:InternalAxiosRequestConfig) => {
  // Do something with the request data
  return config;
}, (error:AxiosError) => {
  // What to do about request errors
  return Promise.reject(error);
});


// Add response interceptor
axios.interceptors.response.use((response:AxiosResponse)=> {
  // Do something with the response data
  return response;
}, (error:AxiosError)=> {
  // Do something about the response error
  return Promise.reject(error);
}); 

Remove interceptor

const myInterceptor = axios.interceptors.request.use((response: AxiosResponse)=> {/*...*/});
axios.interceptors.request.eject(myInterceptor); 

Can be customized axios Example of adding an interceptor

const instance = axios.create();
instance.interceptors.request.use((config:InternalAxiosRequestConfig)=> {/*...*/}); 

Specify the type of return data

responseType Specify the type of return data,This field is not available by default。If this parameter is set,The system will give priority to returning the specified type。 Options include: string:string type; object:Object type; array_buffer:binary array type。 set upresponseTypeback,response.dataThe data in will be of the specified type

 axios<string, AxiosResponse<string>, null>({
    url: 'https://www.xxx.com/info',
    method: 'get',
    responseType: 'array_buffer', 
  }).then((res: AxiosResponse) => {
   // Logic to handle request success
  }) 

Notice:It can also be rewritten bytransformResponsemethod,Modify return data;

 axios<string, AxiosResponse<string>, null>({
    url: 'https://www.xxx.com/info',
    method: 'get',
    responseType: 'array_buffer', 
    transformResponse:(data)=>{
      return data
    }
  }).then((res: AxiosResponse) => {
   // Logic to handle request success
  }) 

customizecaCertificate

 axios<infoModel, AxiosResponse<infoModel>, null>({
    url: 'https://www.xxx.com/xx',
    method: 'get',
    caPath: '', //caCertificate path
  }).then((res: AxiosResponse) => {
    // 
  }).catch((err: AxiosError) => {
    //
  }) 

Custom client certificate

 axios<infoModel, AxiosResponse<infoModel>, null>({
    url: 'https://www.xxx.com/xx',
    method: 'get',
    caPath: '', //caCertificate path
    clientCert: {
        certPath: '', //Client certificate path
        certType: 'p12', // Client certificate type,includepem、der、p12three kinds
        keyPath: '', //Client private key path
        keyPasswd: '' // password
      }
  }).then((res: AxiosResponse) => {
    // 
  }).catch((err: AxiosError) => {
    //
  }) 

Set proxy

 axios<string, AxiosResponse<string>, null>({
      url: 'xxx',
      method: 'get',
      proxy:{
        host: 'xxx',
        port: xx,
        exclusionList: []
      }
    }).then((res: AxiosResponse) => {
      // 
    }).catch((err: AxiosError) => {
      //
    }) 

Certificate pinning

The usage of certificate pinning is as follows:

It is necessary to configure the relevant information of the certificate in the configuration file.:The configuration file path is:entry/src/main/resources/base/profile/network_config.json

Configuration file:network_config

{
  "network-security-config": {
    "domain-config": [
      {
        "domains": [
          {
            "include-subdomains": true,
            "name": "x.x.x.x"  // ipaddress or domain name
          }
        ],
        "pin-set": {
          "expiration": "2024-8-6", //Certificate lock validity period
          "pin": [
            {
              "digest-algorithm": "sha256", //Hash algorithm for message digest,The supported format issha256 
              "digest": "WAFcHG6pAINrztx343ccddfzLOdfoDS9pPgMv2XHk=" //Message summary
            }
          ]
        }
      }
    ]
  }
} 
digestField message summary acquisition

useopensslGet certificate from server,and extract the message summary

openssl s_client -connect host:port 2>&1 < /dev/null \
                    | sed -n '/-----BEGIN/,/-----END/p' \
                    | openssl x509 -noout -pubkey \
                    | openssl pkey -pubin -outform der \
                    | openssl dgst -sha256 -binary \
                    | openssl enc -base64 

Upload and download files

Upload file example
  • Uploaded files need to be imported separatelyFormDatamodule
  • The current version only supports Stage Model
  • Upload type supporturiandArrayBuffer,urisupport“internal”agreement type,Only supports”internal”agreement type,”internal://cache/”is a required field,Example: internal://cache/path/to/file.txt
  • The requested form data value isstringtype
When the uploaded content isArrayBufferhour,Usage is as follows
import axios from '@ohos/axios'
import { FormData } from '@ohos/axios'
import fs from '@ohos.file.fs';

// ArrayBuffer
let formData = new FormData()
let cacheDir = getContext(this).cacheDir
try {
  // write
  let path = cacheDir + '/hello.txt';
  let file = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
  fs.writeSync(file.fd, "hello, world"); // Write data to file in synchronous method
  fs.fsyncSync(file.fd); // Synchronize file data using sync method。
  fs.closeSync(file.fd);

  // read
  let file2 = fs.openSync(path, 0o2);
  let stat = fs.lstatSync(path);
  let buf2 = new ArrayBuffer(stat.size);
  fs.readSync(file2.fd, buf2); // Read data from stream file in synchronous method。
  fs.fsyncSync(file2.fd);
  fs.closeSync(file2.fd);

  formData.append('file', buf2);
} catch (err) {
  console.info('err:' + JSON.stringify(err));
}
// send request
axios.post<string, AxiosResponse<string>, FormData>(this.uploadUrl, formData, {
  headers: { 'Content-Type': 'multipart/form-data' },
  context: getContext(this),
  onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
  console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
},
}).then((res: AxiosResponse) => {
  console.info("result" + JSON.stringify(res.data));
}).catch((error: AxiosError) => {
  console.error("error:" + JSON.stringify(error));
}) 
when uploadedurihour,Usage is as follows
import axios from '@ohos/axios'
import { FormData } from '@ohos/axios'

let formData = new FormData()
formData.append('file', 'internal://cache/blue.jpg')

// send request
axios.post<string, AxiosResponse<string>, FormData>('https://www.xxx.com/upload', formData, {
  headers: { 'Content-Type': 'multipart/form-data' },
  context: getContext(this),
  onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
    console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
  },
}).then((res: AxiosResponse<string>) => {
  console.info("result" + JSON.stringify(res.data));
}).catch((err: AxiosError) => {
  console.error("error:" + JSON.stringify(err));
}) 
Download file example

Set download pathfilePath(Default in’internal://cache/’under path)。

aboutfilePath
filePath:‘workspace/test.txt’:Created under default pathworkspacepath,and store the file inworkspaceunder path。
filePath:‘test.txt’:Store files under default path。
filePath:‘workspace/’:Created under default pathworkspacepath,and store the file inworkspaceunder path。

  • The current version only supports Stage Model When downloading a file,iffilePathIf the file already exists, the download fails.,Files need to be deleted before downloading。
let filePath = getContext(this).cacheDir + '/blue.jpg'
// download。if the file already exists,then delete the file first。
try {
  fs.accessSync(filePath);
  fs.unlinkSync(filePath);
} catch(err) {}

axios({
  url: 'https://www.xxx.com/blue.jpg',
  method: 'get',
  context: getContext(this),
  filePath: filePath ,
  onDownloadProgress: (progressEvent: AxiosProgressEvent): void => {
    console.info("progress: " + progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) : 0)
  }
}).then((res)=>{
  console.info("result: " + JSON.stringify(res.data));
}).catch((error)=>{
  console.error("error:" + JSON.stringify(error));
}) 

Error handling

Error handling sample code
axios.get<string, AxiosResponse<string>, null>('/user/12345')
  .catch((error:AxiosError)=> {
    console.log(JSON.stringify(error.message));
    console.log(JSON.stringify(error.code));
    console.log(JSON.stringify(error.config));
  }); 
error code
  • When the network request is abnormal,catchMethod received exception,Exception error code [Please click to view]
  • error constant
name Parameter Type readable writable illustrate
NETWORK_MOBILE number yes no Bit flag to allow downloading when using cellular networks。
NETWORK_WIFI number yes no useWLANbit flag to allow downloading。
ERROR_CANNOT_RESUME7+ number yes no Recovery download failed due to some temporary errors。
ERROR_DEVICE_NOT_FOUND7+ number yes no not foundSDCards and other storage devices。
ERROR_FILE_ALREADY_EXISTS7+ number yes no The file to download already exists,Download sessions cannot overwrite existing files。
ERROR_FILE_ERROR7+ number yes no File operation failed。
ERROR_HTTP_DATA_ERROR7+ number yes no HTTPTransfer failed。
ERROR_INSUFFICIENT_SPACE7+ number yes no not enough storage space。
ERROR_TOO_MANY_REDIRECTS7+ number yes no Error caused by too many network redirects。
ERROR_UNHANDLED_HTTP_CODE7+ number yes no UnrecognizedHTTPcode。
ERROR_UNKNOWN7+ number yes no unknown mistake。
PAUSED_QUEUED_FOR_WIFI7+ number yes no Download paused and waitingWLANconnect,Because the file size exceeds the maximum allowed for sessions using cellular networks。
PAUSED_UNKNOWN7+ number yes no Download paused for unknown reasons。
PAUSED_WAITING_FOR_NETWORK7+ number yes no due to network problems(For example, the network is disconnected)and pause the download。
PAUSED_WAITING_TO_RETRY7+ number yes no A network error occurred,Download session will be retried。
SESSION_FAILED7+ number yes no Download session failed,will not retry。
SESSION_PAUSED7+ number yes no Download session paused。
SESSION_PENDING7+ number yes no Scheduling download session。
SESSION_RUNNING7+ number yes no Download session in progress。
SESSION_SUCCESSFUL7+ number yes no Download session completed。

This article is reproduced from https://blog.csdn.net/m0_62167422/article/details/136976527,If there is any infringement,Please contact to delete。