Skip to content

http-data-request

A flexible network data request library based on axios with additional features

GitHub Repo stars GitHub forks

Repository status

CircleCI code coverage npm version license JavaScript Style Guide

Detailed changes for each release are documented in Changelog

Features

  • Automatically save and apply authorization tokens
  • Unified handling of exception information
  • Customizable status code
  • Customizable authorization data node
  • Provides quick access functions for each request method
  • Provides a function to cancel all current requests

Design Background

http-data-request is suitable for scenarios where a custom encoding system is applied for web and server interaction applications, rather than directly using the native HTTP status code scheme

Business Data Format

The server responds to system business requests with HTTP 200 status, and the response data format is as follows:

json
{
  // Business status code
  "code": 0,
  // Business exception information, only outputs "ok" in non-exceptional cases
  "msg": "ok",
  // Business data
  "data": {}
}

The business status code code usually has the following situations:

  • 0 Request successful
  • 10 Access token invalid
  • 11 Refresh token invalid
  • Other business exceptions

Authentication Mode

The plugin provides two authentication modes, the difference between the two lies in how to handle the expiration of the authentication token

Successful Authentication Process

login-success

In the process, both store the token in local storage and carry the token to make requests are actions automatically handled by the plugin

Failed Authentication Process

Dual Token Mode

The application access token is short-term, and the refresh token is long-term.

  • Carry access token to execute data request
  • Respond with access token invalid status { code: 10, ... }
  • http-data-request automatically uses the refresh token to send a request to refresh the access token
  • If the response is successful, update the token-related information and re-initiate the data request
  • If the response fails, it is considered that the user's authentication has expired and needs to log in again { code: 11, ... }

refresh-token-invalid

Single Token Mode

The application access token is long-term

  • Carry access token to execute data request
  • Respond with refresh token invalid status { code: 11, ... }
  • If it fails, it is considered that the user's authentication has expired and needs to log in again

access-token-invalid

Installation

Install the http-data-request component into your project

sh
npm i http-data-request
sh
yarn add http-data-request
sh
pnpm add http-data-request

Add a file in the project, such as /src/config/http/index.js, to set the global configuration of http-data-request and export various functional functions

ts
import { useHttpDataRequest } from 'http-data-request'
import type { HttpDataRequestOptions } from 'http-data-request'

const options: HttpDataRequestOptions = {
  baseUrl: 'https://example.com/api',
}

export const {
  http, get, post, put, patch, del, cancel
} = useHttpDataRequest(options)

In the Vite configuration file vite.config.js, set an alias for the project installation module directory for http

js
import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'
import { defineConfig } from 'vite'

export default defineConfig({
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      '@api': fileURLToPath(new URL('./src/api', import.meta.url)),
      '@http': fileURLToPath(new URL('./src/config/http', import.meta.url))
    }
  },
  ...
})

After applying the above configuration, in any position of the project, you can directly use the @http aliases to use HTTP related functions

Basic Setup

Quick Functions

In the function set created by useHttpDataRequest, the http function is the core function for data requests, while get, post, put, patch, and del are quick functions for each request method

js
get('/user/1')
// Equivalent to
http('/user/1', undefined, { method: 'GET' })

The default request method for http is POST

URL

If the provided URL is a relative path, it will be automatically concatenated with baseUrl

js
const options: HttpDataRequestOptions = {
  baseUrl: 'https://example.com/api',
}

get('/user/1')

In this case, the actual request is to https://example.com/api/user/1.

js
get('https://other-example.com/api/user/1')

If the URL starts with http/https, it will directly use that address without concatenating baseUrl

This setup provides the convenience of quickly applying the base address within the system while retaining the flexibility to directly access other website addresses

Mismatched response format

Use http-data-request to request data successfully. The response format is as follows

ts
interface HttpDataRequestBody{
  code: number
  msg: string
  data: any
}

If the response data format does not match HttpDataRequestBody, the data will be returned directly, but at the same time, global exception handling will not take effect in the current request

Examples for apply

Project API Definition

js
// src/api/user.js
import { get, post } from '@http'

export function getUser(userId) {
  return get(`/user/${userId}`)
}

Used in Components/Pages

vue
<template>
  <div>
    <div>
      User name: {{ user.name }}
    </div>
    <div>
      User age: {{ user.age }}
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import { getUser } from '@api/user'

const user = ref({})

getUser(10).then(data => { user.value = data })
</script>

Cancel Request

Cancel all currently executing requests

vue
<template>
  <div>
    <div>
      ...order form
    </div>
    <button
      type="button"
      @click="save"
    >Save order</button>
    <!--
    Clicking before the data is saved successfully
    will cancel the data request
    -->
    <button
      type="button"
      @click="cancel"
    >Cancel</button>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import { DialogMessageSuccess } from 'v-dialogs'
import { cancel } from '@http'
import { saveOrder } from '@api/order'

function save() {
  saveOrder({ ...formData }).then(() => {
    DialogMessageSuccess('Order saved successfully')
  })
}
</script>

Global Configuration

Here, the v-dialogs component is used as an example to display exception information content in the dialog

ts
import {
  useHttpDataRequest,
  EXCEPTION_BUSINESS,
  EXCEPTION_AUTH_INVALID
} from 'http-data-request'
import type { HttpDataRequestOptions } from 'http-data-request'
import { DialogMessageError, DialogAlertError } from 'v-dialogs'
import { logout } from './auth'

const options: HttpDataRequestOptions = {
  baseUrl: 'https://example.com/api',
  // global exception handle
  exception (message, type) {
    // display business exceptions message
    if (type === EXCEPTION_BUSINESS) {
      DialogMessageError(message)
      return
    }
    // display rest of other exceptions message
    DialogAlertError(message)
    // some action for user authorization expired
    if (type === EXCEPTION_AUTH_INVALID) {
      // cancel all current request when
      cancel()
      // logout and redirect to login page
      logout()
    }
  }
}

export const {
  http, get, post, put, patch, del, cancel
} = useHttpDataRequest(options)

The above code is a typical application of global exception handling in the project, which has three parts of processing content

  • Silently display business exception information
  • Modal prompts other exception information, which requires user confirmation before continuing, such as system underlying exceptions, network exceptions, identity authentication failure, etc.
  • When the identity token expires, cancel all current requests and log out

After setting up global exception handling, various types of exception information will be automatically displayed, so there is no need to handle exception information in the business code, just focus on processing business logic

Applying environment variables

The baseUrl option specifies the base URL prefix for network requests. In actual project applications, different addresses need to be set for different working environments.

Take the vite tool chain as an example, create the following three .env environment configuration files in the project

bash
# .env.development
VITE_BASE_URL=https://exapmle-dev.com/api

# .env.alpha
VITE_BASE_URL=https://exapmle-test.com/api

# .evn.production
VITE_BASE_URL=https://exapmle.com/api

After setting the environment variable configuration, access the variable content through import.meta.env.VITE_SOME_KEY

ts
const options: HttpDataRequestOptions = {
  baseUrl: import.meta.env.VITE_BASE_URL
}

In this way, when developing or building in different environments, the basic network addresses specified by different environments will be automatically applied

Request header authorization token

After successful login, subsequent data requests will add an authorization token to the request header. The following fields will be added by default

js
{
  'Authorization': 'Bearer access-token-value'
}

Custom property names and settings without the Bearer prefix

ts
const options: HttpDataRequestOptions = {
  tokenPrefix: false,
  keys: {
    header: 'x-http-request-access-token'
  }
}

Applying this setting, the token attribute and value carried in the request header are as follows

js
{
  'x-http-request-access-token': 'access-token-value'
}

Response status code

Assume that the status code scheme of the server response is as follows

json
// success
{ "code": 1000, "msg": "ok", "data": { ... } }
// access token invalid
{ "code": 1100, "msg": "access token invalid", "data": {} }
// refresh token invalid
{ "code": 1200, "msg": "refresh token invalid", "data": {} }

According to the status code of the server response, set the custom status code item in the statuses option as follows

ts
const options: HttpDataRequestOptions = {
  baseUrl: 'https://example.com/api',
  statuses: {
    success: 1000,
    invalidAccessToken: 1100,
    invalidRefreshToken: 1200
  }
}

In this way, http-data-request corresponds to the various status codes of the server response.

Authorization data node

http-data-request will automatically grab the authorization token and save the data to LocalStorage. The default data format matched by the plugin is as follows

js
{
  access: {
    accessToken: 'access-token-value',
    refreshToken: 'refresh-token-value',
    expiresIn: 10086
  }
}

When the plug-in processes the data request and returns the result, it will always detect whether there is an access data node, and automatically store or replace it if it exists. This mechanism does not require manual processing of the operation of saving token information to local storage, and unifies the location and behavior of local storage of token information

This mechanism can also be used to implement the function of automatic login

ts
const options: HttpDataRequestOptions = {
  keys: {
    dataSet: 'accessData',
    accessToken: 'accessTokenKey',
    refreshToken: 'refreshTokenKey',
    expiresIn: 'expiresOn'
  }
}

This custom node setting matches the response data format of the following server

js
{
  accessData: {
    accessTokenKey: 'access-token-value',
    refreshTokenKey: 'refresh-token-value',
    expiresOn: 10086
  }
}

When the access token expires, the plugin will automatically initiate a request to refresh the token (the location of the request is specified by the refreshUrl option). The data body of the request is as follows

js
{
  refreshToken: 'refresh-token-value'
}

If you need to customize the field name of the request body, you can set it through the keys.paramRefreshToken option

ts
const options: HttpDataRequestOptions = {
  keys: {
    paramRefreshToken: 'refreshTokenValue'
  }
}

After applying this setting, the request body sent when refreshing the access token is as follows

js
{
  refreshTokenValue: 'refresh-token-value'
}

API

http-data-request setup function for project

ts
function useHttpDataRequest(
  options: HttpDataRequestOptions
): HttpDataRequestMethods

useHttpDataRequest input parameters HttpDataRequestOptions type description

ts
interface HttpDataRequestOptions {
  /**
   * Plugin language
   * @default `en`
   */
  language?: LanguageType
  /**
   * Base url path
   * @default `/`
   */
  baseUrl: string
  /**
   * The url used to refresh new access token
   * @default `/auth/refresh-token`
   */
  refreshUrl?: string
  /**
   * @default 0
   */
  expiresIn?: number
  /**
   * Specifies the number of milliseconds before the request times out
   * @default 10000
   */
  timeout?: number
  /**
   * Customize the key name of the data node
   */
  keys?: {
    /**
     * Access data node name
     * @default `access`
     */
    dataSet?: string
    /**
     * Access token property name
     * @default `accessToken`
     */
    accessToken?: string
    /**
     * Refresh token property name
     * @default `refreshToken`
     */
    refreshToken?: string
    /**
     * Token expires in property name
     * @default `expiresIn`
     */
    expiresIn?: string
    /**
     * The property name in the request body to pass refresh token
     * @default `refreshToken`
     */
    paramRefreshToken?: string
    /**
     * The property name of the request headers to pass access token
     * @default `Authorization`
     */
    header?: string
  }
  /**
   * Customize the status code of the response
   */
  statuses?: {
    /**
     * Success status code
     * @default 0
     */
    success?: number
    /**
     * Access token invalid status code
     * @default 10
     */
    invalidAccessToken?: number
    /**
     * Refresh token invalid status code
     * @default 11
     */
    invalidRefreshToken?: number
  }
  /**
   * Request exception handle
   */
  exception?: (message: string, type: EXCEPTION_TYPE) => void
}

type EXCEPTION_TYPE =
  | 'exception-business'
  | 'exception-auth-invalid'
  | 'exception-system'

The type description of the function set HttpDataRequestMethods created after executing useHttpDataRequest

ts
interface HttpDataRequestMethods {
  /**
   * Core function of HTTP data request
   */
  http: typeof HttpDataRequest
  /**
   * Quick functions for get, post, put, patch, and delete request methods
   */
  get: typeof HttpDataRequest
  post: typeof HttpDataRequest
  put: typeof HttpDataRequest
  patch: typeof HttpDataRequest
  del: typeof HttpDataRequest
  /**
   * Cancel all current requests
   */
  cancel: () => void
}

function HttpDataRequest(
  // Data request URL
  url: string,
  // Request data
  data: any,
  // Native axios request configuration parameters
  options: AxiosRequestConfig
): Promise<any>

For the complete axios config, please visit axios-request-config

Released under the MIT License.