# gloam-http
**Repository Path**: moxy-hub/gloam-http
## Basic Information
- **Project Name**: gloam-http
- **Description**: 基于axios封装的http基础能力包
- **Primary Language**: TypeScript
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 5
- **Forks**: 0
- **Created**: 2024-03-14
- **Last Updated**: 2024-12-24
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
GLOAM-HTTP
> gloam-http 源于日常项目开发中进行的重复性劳动,使用 ts 封装 axios,更加快捷方便的使用方法,支持 filter 过滤器、过滤器排序、token 认证、body 体加密,内置事件系统,支持业务系统的感知处理
## 版本更新
> - 2024.12.24 -【1.1.5】
>
> - 新增过滤器排除配置
> - 独立 token 过滤器
>
> - 2024.11.27 -【1.1.4】
>
> - 优化 ras 公钥的获取为 promise,支持异步获取
>
> - 2024.8.14 -【1.1.3】
>
> - 修复解密结果不正确的异常
>
> - 2024.8.14 -【1.0.9】
>
> - 修复加密请求中,对于请求体为空的请求无法传输密钥加密响应的问题
>
> - 2024.3.15 -【1.0.6】发布 🚀
> - 基于 ts 封装 axios,实现请求的快捷使用
> - 封装 axios 的拦截器,增加 filter 过滤器,支持过滤器排序执行
> - 新增事件系统,支持系统内部多种事件的感知
> - 增强 axios 创建的配置参数,使用 httpClient 进行创建
> - 配置支持同一添加前缀,时间戳等
> - 支持 token 认证,采用 aes 加密方式进行传输,需要后端同样适配
> - 支持 body 体加密,采用 rsa+aes 的信封加密方式
## 快速开始
- 安装
> NPM 镜像安装
```shell
npm install gloam-http
```
- 实例
```typescript
// 基础配置
const options: HttpClientOptions = {};
// 实例化客户端
const httpClient = new HttpClient(options);
// 导出使用
export { httpClient };
```
- 使用
```typescript
const res = await httpClient.get({url: "http://www.baidu.com"}})
```
## 基础配置
### 1、HttpClientOptions
> 在实例化 HttpClient 时的配置,属于全局配置,适用于每一个请求
| 配置字段 | 配置说明 |
| :------------: | :--------------------------------------------------------: |
| requestOptions | 请求基础配置,详见[RequestOptions](# 2、RequestOptions) |
| requestToken | 请求 token 基础配置,详见[RequestToken](# 3、RequestToken) |
| webEnvelope | 请求体加密基础配置,详见[WebEnvelope](# 4、WebEnvelope) |
| filters | 过滤器基础配置,详见[Filter](# 5、Filter) |
| event | 事件基础配置,详见[HttpEvent](# 6、HttpEvent) |
**案例**
```typescript
const options: HttpClientOptions = {
requestOptions: {},
requestToken: {},
webEnvelope: {},
filters: [],
event: {},
};
// 实例化客户端
const httpClient = new HttpClient(options);
// 导出使用
export { httpClient };
```
### 2、RequestOptions
> 配置请求的基本参数
| 配置字段 | 配置说明 | 类型 | 默认 |
| :-------------: | :----------------------------------------------------------: | ------- | ----- |
| joinParamsToUrl | post 请求的时候添加参数到 url | boolean | false |
| formatDate | 格式化提交参数时间,会将时间数据格式化为 YYYY-MM-DD HH:mm:ss | boolean | false |
| joinPrefix | 默认将 prefix 添加到 url,prefix 配置为 urlPrefix | boolean | false |
| urlPrefix | 接口拼接地址 | string | ‘’ |
| apiUrl | 接口地址 | string | ‘’ |
| joinTime | 是否加入时间戳,会在 GET 请求后面加上时间戳参数 | boolean | true |
**案例**
```typescript
const options: HttpClientOptions = {
requestOptions: {
joinParamsToUrl: true,
formatDate: true,
joinPrefix: true,
urlPrefix: "service-gateway",
apiUrl: "http://127.0.0.1",
joinTime: true,
},
};
// 实例化客户端
const httpClient = new HttpClient(options);
// 导出使用
export { httpClient };
```
### 3、RequestToken
> 请求携带 token 的相关配置
| 配置字段 | 配置说明 | 类型 | 默认 |
| :------------------: | :-------------------: | :-----: | :---: |
| enable | 是否开启 token 认证 | boolean | false |
| authenticationScheme | 认证信息前缀 | string | "" |
| aesKey | 认证信息 aes 加密密钥 | string | "" |
| split | 认证信息 token 分割 | string | "" |
**案例**
```typescript
const options: HttpClientOptions = {
requestToken: {
enable: true,
authenticationScheme: "bearer",
aesKey: "485s8s8d4df8df1f8aqw5f8f49d5ew78",
split: "-SPLIT-",
},
};
// 实例化客户端
const httpClient = new HttpClient(options);
// 导出使用
export { httpClient };
```
### 4、WebEnvelope
> 请求体加密参数
| 配置字段 | 配置说明 | 类型 | 默认 |
| :------: | :--------------------: | :-----: | :---: |
| enable | 是否开启开启请求体加密 | boolean | false |
**案例**
```typescript
const options: HttpClientOptions = {
webEnvelope: {
enable: true,
},
};
// 实例化客户端
const httpClient = new HttpClient(options);
// 导出使用
export { httpClient };
```
### 5、Filter
> 请求过滤器
| 配置字段 | 配置说明 | 类型 | 默认 |
| :------: | :------------------------: | :------------: | :--: |
| filters | 配置实现 Filter 接口的对象 | Array\ | [ ] |
**案例**
```typescript
const options: HttpClientOptions = {
filters: [
// 外部实现的filter
MyFilter,
// 内部实现的filter
{
order(): number {
return 0;
},
},
],
};
// 实例化客户端
const httpClient = new HttpClient(options);
// 导出使用
export { httpClient };
```
### 6、HttpEvent
> 请求事件系统
| 配置字段 | 配置说明 | 类型 | 默认 |
| :------: | :-------------------------: | :---: | :--: |
| event | 配置实现 Event 抽象类的对象 | Event | { } |
**案例**
```typescript
const options: HttpClientOptions = {
event: {
onNetworkError(error: Error, defaultMessage: string): void {
console.log("网络错误了", error, defaultMessage);
},
},
};
// 实例化客户端
const httpClient = new HttpClient(options);
// 导出使用
export { httpClient };
```
## Filter
> 过滤器的实现是基于 Axios 的请求响应拦截原理,在其基础上增强了顺序编排,在 Gloam-Http 中存在三个默认的执行器
### 1、接口
```typescript
export interface Filter {
/**
* @description: 请求拦截器
*/
request?: (
config: InternalRequestConfig,
options: HttpClientOptions
) => InternalRequestConfig;
/**
* @description: 响应拦截器
*/
response?: (
res: AxiosResponse | Result,
options: HttpClientOptions
) => AxiosResponse | Result;
/**
* @description: 请求之前的拦截器错误处理
*/
requestCatch?: (error: Error, options: HttpClientOptions) => void;
/**
* @description: 请求之后的拦截器错误处理
*/
responseCatch?: (
axiosInstance: AxiosInstance,
error: Error,
options: HttpClientOptions
) => Promise;
/**
* @description: 执行顺序
*/
order: () => number;
}
```
### 2、默认拦截器
- **DefaultFilter**
> 执行顺序为 0
>
> **【请求过滤器】**:主要负责对请求的基础配置,配置 RequestOptions 参数以及 Token 相关参数
>
> **【响应过滤器】**:主要负责监听响应头中携带的 Token 信息,通过事件模块进行业务的感知
- **EncryptFilter**
> 执行顺序为 1
>
> **【请求过滤器】**:主要负责对需要加密的请求进行数据加密操作
>
> **【响应过滤器】**:主要负责对响应的数据进行解密
- **TimeFilter**
> 执行顺序为 1
>
> **【请求过滤器】**:主要负责对请求中数据为‘createTimeStart’和‘createTimeEnd’的字段进行时间处理,格式为时间戳
### 3、实现案例
```typescript
export const timeFilter: Filter = {
order(): number {
return 2;
},
request(
config: InternalRequestConfig,
_options: HttpClientOptions
): InternalRequestConfig {
// 处理get请求的时间格式,统一变成时间戳
const params = config.params;
if (!params) {
return config;
}
if (params.createTimeStart) {
params.createTimeStart = format2Timestamp(params.createTimeStart);
}
if (params.createTimeEnd) {
params.createTimeEnd = format2Timestamp(params.createTimeEnd);
}
return config;
},
};
```
## Event
> 通过事件系统,可以让业务系统感知到请求的节点,配合完成整个请求链路
### 1、抽象类
```typescript
export abstract class HttpEvent {
/**
* 在状态错误的请况下,状态不为200
*/
onStatusError?: (error: Error, statusCode: number, massage: string) => void;
/**
* 请求超时错误
*/
onTimeoutError?: (error: Error, defaultMessage: string) => void;
/**
* 网络错误
*/
onNetworkError?: (error: Error, defaultMessage: string) => void;
/**
* 请求结果感知,可以全局拦截到请求结果,进行预处理
*/
webResultAware?: (result: Result, url?: string) => void;
/**
* 响应token感知,如果响应存在token,则会进行感知
*/
authorizationTokenAware?: (token: string) => void;
/**
* 注入token,在每个请求发送时会调用此事件获取token
*/
authorizationTokenInfuse?: () => string;
/**
* 注入rsa加密公钥,请求加解密时必须传入
* requestConfig: HttpClientInternalRequestConfig
*/
rsaPublicKeyInfuse?: () => string;
}
```
## Token
### 1、实现原理
> - 在进行携带 token 时,会先调用**事件系统**的‘authorizationTokenInfuse( )’方法获取到由业务系统保管的 token
>
> - 请求中会生成 nonce 字段(由配置的 aesKey 加密)放入请求头 nonce
>
> - 请求会将 token 按照一定顺序拼接,然后使用配置的 aesKey 加密,放入请求头 Authorization
>
> > 加密排列:nonce + splip(配置的分隔符) + Date.now().toString() + splip(配置的分隔符) + token;
### 2、结合事件系统进行 token 的获取与注入
> 在后端生成 token 后,应该放置 Authorization 请求头,gloam-http 会解析每次响应的 token,如果存在则会调用**事件系统**的 authorizationTokenAware( )方法,此时业务系统应该将 token 存入本地缓冲,并在**事件系统**的 authorizationTokenInfuse( )方法中将 token 重新交与 gloam-http
## WebEnvelope
### 1、原理
- 请求加密的使用需要后端配合提供 RSA 公钥或获取公钥的接口,在**事件系统**中由 rsaPublicKeyInfuse( )方法告知 gloam-http
- gloam-http 在发送请求时,将会随机生成 aesKey,由 aesKey 对数据进行加密,然后由后端提供的公钥将 aesKey 进行加密
- 请求后端的格式
```json
{
"data": "由aes加密的数据",
"key": "由rsa加密的aesKey"
}
```
### 2、使用
- 在之前的创建实例的配置中,存在是否开启加密的参数,需要注意的是该参数为 true 时表示加密功能可用,不是全部请求加密,如果为 false 则表示全局不使用加密,在局部配置也是无效的
- GET 请求或者 body 中为空时不会进行加密
- 在创建实例时开启加密功能的情况下,如下使用:
```typescript
const res = await httpClient.get({
url: "http://www.baidu.com",
encrypt: true,
data: {
a: "传输中会被加密",
},
});
```
## 参与贡献
1. **Fork 本仓库**
2. **新建 Feat_xxx 分支**
3. **提交代码**
4. **新建 Pull Request**
**【注】:commit 时请将修改信息填写清楚**