npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

api-interceptor

v1.4.10

Published

api interceptor in applets-request

Readme

api-interceptor

接口拦截器

Introduction

用于接口请求库实现签名、获取 token 以及更新 token 等功能,通过在拦截器(interceptor)中计算签名,并赋值到headers["Authorization-Sign"]。适用于applets-request-mode-listaxios等实现拦截器的库。

  • 特别注意:由于request interceptor的执行逻辑是先添加的后执行,所以如果签名中需要加入Authorization-Token一起参与签名,则sign-interceptor拦截器需要在获取 token 前加入拦截器

注意事项

拦截器执行顺序

  • 使用addRequestInterceptor添加请求拦截器时,先添加的拦截器函数,后执行,是一个栈的结构,先进后出。需要特别注意顺序
  • 使用addResponseInterceptor添加响应拦截器时,先添加的拦截器函数,先执行,是一个队列的结构,先进先出。

Install

npm install git+ssh://[email protected]:common/api-interceptor.git#Tag

Install Example

npm install git+ssh://[email protected]:common/api-interceptor.git#v1.3.1

API

signInterceptor(appKey, appCode)

返回一个函数,用于执行签名计算

getTokenRequestInterceptor(getToken)

返回一个函数,用于执行获取 token

refreshTokenResponseInterceptor(isRefresh, getToken)

返回一个函数,用于执行重新获取 token,并用新的 token 自动重新发起一次请求

generateErrorLog(err)

返回Json数据,用于生成接口请求的错误日志信息

generateRequestAfterLog(res)

返回Json数据,用于生成接口响应的日志信息

generateRequestBeforeLog(config)

返回Json数据,用于生成接口请求前的日志信息

Demo

import ApiHttp from "applets-request-mode-list";
import {
  signInterceptor,
  getTokenRequestInterceptor,
  refreshTokenResponseInterceptor,
  responseFormatterInterceptor,
  generateErrorLog,
  generateRequestAfterLog,
  generateRequestBeforeLog,
} from "api-interceptor";
import { getToken } from "mini-auth-v1";

// 接口配置
const apiList = {
  getDemo: {
    apiUrl: "/get/demo",
    method: "POST",
    /**
     * 重试次数
     *
     * 可选配置:默认2
     */
    retryTimes: 3,

    /**
     * 重试间隔时间
     *
     * 可选配置:默认2000
     */
    interval: 3000,
  },
};

function createApiHttp(
  options,
  reqConfig = {},
) {
  // 构建接口请求对象
  const api = new ApiHttp(options, reqConfig);

  // 设置请求超时时间
  api.appletsRequest.defaults.timeout = 10000;

  // 添加request拦截器,计算签名,先于获取token的拦截器
  api.addRequestInterceptor((config) => {
    if (config.apiConfig.skipSign === false) {
      return config;
    }
    const interceptor = signInterceptor("API_APP_KEY", "API_APP_CODE");
    return interceptor(config);
  });

  // 添加获取token拦截器
  api.addRequestInterceptor(async (config) => {
    if (config.apiConfig.requireToken === false) {
      return config;
    }
    // 传入getToken方法
    const interceptor = getTokenRequestInterceptor(getToken);
    // 执行 interceptor(config) 后,会在 config.tokenInterceptData 中增加 getToken 获取到的原始数据
    // 按需使用tokenInterceptData中的数据
    const intercept = await interceptor(config);
    return intercept;
  });

  // 添加请求前日志
  api.addRequestInterceptor((config) => {
    const logInfo = generateRequestBeforeLog(config);
    // logInfo = {
    //   v3: "",
    //   msg: "",
    //   request: string or object
    // }
    // 生成的logInfo可用于投递到日志系统中
    return config;
  });

  /**
   * 记录请求返回日志
   */
  api.addResponseInterceptor((res) => {
    const logInfo = generateRequestAfterLog(res);
    // logInfo = {
    //   v3: "",
    //   msg: "",
    //   request: string or object,
    //   response: string or object,
    // }
    // 可以使用logInfo,投递到日志系统
    return res;
  });

  api.addResponseInterceptor((res) => {
    // refreshTokenResponseInterceptor需要两个参数:isRefresh 和 getToken
    // 第一个参数判断是否是要重新请求,类型boolean,true表示重新请求token,执行getToken逻辑
    // 第二个参数获取token的方法:getToken
    const interceptor = refreshTokenResponseInterceptor(
      res.data.code === 40003,
      getToken,
    );
    return interceptor(res);
  });

  // 格式化输出请求返回数据
  api.addResponseInterceptor((responseFormatterInterceptor);

  /**
   * 记录请求返回错误日志
   */
  api.addResponseInterceptor((res) => res, (err) => {
    const logInfo = generateErrorLog(err);
    // logInfo = {
    //   v3: "",
    //   msg: "",
    //   request: string or object,
    //   response: string or object,
    // }
    // 可以使用logInfo,投递到日志系统
    return Promise.reject(err);
  });

  /**
   * 格式化错误信息
   */
  api.addResponseInterceptor((res) => res, responseErrorFormatter);

  return api;
}

const apiHttpOptions = {
  baseURL: "https://xxx.com",
  apiList,
};

// 设置所有的Content-Type为"application/json; charset=utf-8"
const requestConfig = {
  headers: {
    "Content-Type": "application/json; charset=utf-8",
  },
};

const apiObj = createApiHttp(apiHttpOptions, requestConfig);

export default apiObj.apis;

export { apiObj as apiHttp };

export { createApiHttp as createApiHttp };

// 接口请求示例
apiObj.apis.getDemo().then().catch();

TypeScript 版 Demo

/* eslint-disable space-before-function-paren */
import ApiHttp from "applets-request-mode-list";
import {
  signInterceptor,
  getTokenRequestInterceptor,
  refreshTokenResponseInterceptor,
  responseFormatterInterceptor,
  responseErrorFormatterInterceptor,
  generateErrorLog,
  generateRequestBeforeLog,
  generateRequestAfterLog,
} from "api-interceptor";
import { getToken } from "mini-auth-v1";

// 接口配置
const apiList = {
  getDemo: {
    apiUrl: "/get/demo",
    method: "POST",
    /**
     * 重试次数
     *
     * 可选配置:默认2
     */
    retryTimes: 3,

    /**
     * 重试间隔时间
     *
     * 可选配置:默认2000
     */
    interval: 3000,
  },
};

interface IAppletsResSuccess<IData = any> {
  retcode: number;
  msg: string;
  data: IData;
}

type IMainApis<IApiFn> = {
  [K in keyof IApiFn]: IApiFn[K] extends {
    params: Record<string, any>;
  }
    ? <IParam>(
        opts: IAppletsRequestConfig<IParam>,
      ) => Promise<IAppletsResSuccess<any>>
    : (opts: IAppletsRequestConfig | void) => Promise<IAppletsResSuccess<any>>;
};

interface ICreateApiHttpOptions {
  baseURL: string;
  apiList: IAppletsApi.IApiList;
}

/**
 * 创建请求对象实例
 * @param options ICreateApiHttpOptions
 * @param reqConfig IAppletsRequestConfig
 */
function createApiHttp<T = null>(
  options: ICreateApiHttpOptions,
  reqConfig?: IAppletsRequestConfig,
): ApiHttp<T> {
  const api = new ApiHttp<T>(options, reqConfig);

  api.appletsRequest.defaults.timeout = 10000;

  // 添加签名拦截器
  api.addRequestInterceptor((config) => {
    if (config.apiConfig.skipSign === false) {
      return config;
    }
    const interceptor = signInterceptor("API_APP_KEY", "API_APP_CODE");
    return interceptor(config);
  });

  // 添加获取token拦截器
  api.addRequestInterceptor(async (config) => {
    if (config.apiConfig.requireToken === false) {
      return config;
    }
    const interceptor = getTokenRequestInterceptor(getToken);
    // 执行 interceptor(config) 后,会在 config.tokenInterceptData 中增加 getToken 获取到的原始数据
    // 按需使用tokenInterceptData中的数据
    const intercept = await interceptor(config);
    return intercept;
  });

  // 添加请求前日志
  api.addRequestInterceptor((config) => {
    const logInfo = generateRequestBeforeLog(config);
    // logInfo = {
    //   v3: "",
    //   msg: "",
    //   request: string or object
    // }
    // 生成的logInfo可用于投递到日志系统中
    return config;
  });

  /**
   * 记录请求返回日志
   */
  api.addResponseInterceptor((res) => {
    const logInfo = generateRequestAfterLog(res);
    // logInfo = {
    //   v3: "",
    //   msg: "",
    //   request: string or object,
    //   response: string or object,
    // }
    // 可以使用logInfo,投递到日志系统
    return res;
  });

  // 添加更新token拦截器
  api.addResponseInterceptor((res) => {
    const interceptor = refreshTokenResponseInterceptor(
      // 需要更新token的错误码
      [40003, 40001].includes(res.data.code),
      getToken,
    );
    return interceptor(res);
  });

  // 格式化输出请求返回数据
  api.addResponseInterceptor(responseFormatterInterceptor);

  /**
   * 记录请求返回错误日志
   */
  api.addResponseInterceptor((res) => res, (err) => {
    const logInfo = generateErrorLog(err);
    // logInfo = {
    //   v3: "",
    //   msg: "",
    //   request: string or object,
    //   response: string or object,
    // }
    // 可以使用logInfo,投递到日志系统
    return Promise.reject(err);
  });

  /**
   * 格式化错误信息
   */
  api.addResponseInterceptor((res) => res, responseErrorFormatterInterceptor);

  return api;
}

const apiHttpOptions = {
  baseURL: "HOST",
  apiList: apiList as IAppletsApi.IApiList,
};

// 设置所有的Content-Type为"application/json; charset=utf-8"
const requestConfig = {
  headers: {
    "Content-Type": "application/json; charset=utf-8",
  },
};

const apiObj = createApiHttp<IMainApis<typeof apiList>>(apiHttpOptions, requestConfig);

export default apiObj.apis;

export { apiObj as apiHttp };

export { createApiHttp as createApiHttp };

// 接口请求示例
// options和axios中的参数一致
apiObj.apis.getDemo(options).then().catch();

signInterceptor参数

appKey

Type: String

接口签名的appKey,对应于``headersAuthorization-AppKey`

appCode

Type: String

接口签名的appCode或者secret

getTokenRequestInterceptor参数

getToken

Type: Function

用于获取 token

refreshTokenResponseInterceptor参数

isRefresh

Type: Boolean

是否重新获取 token

getToken

Type: Function

依赖

点击查看applets-request-mode-list