HTTP 请求
简单的 HTTP 请求
Midway 内置了一个简单的 HTTP 请求客户端,无需引入三方包即可使用。
默认 Get 请求,返回数据为 Buffer。
内置的 Http 客户端只提供最简单的能力,仅满足大部分的前端接口数据获取,如需复杂的功能,比如文件上传等,请使用其他的客户端,如 fetch,axios,got 等。
简单方法形式
import { makeHttpRequest } from '@midwayjs/core';
const result = await makeHttpRequest('http://127.1:7001/');
// Buffer.isBuffer(result.data) => true
Get 请求,带上 Query,返回类型为 JSON。
import { makeHttpRequest } from '@midwayjs/core';
const result = await makeHttpRequest('http://127.1:7001/', {
data: {
a: 1,
b: 2
},
dataType: 'json', // 返回的数据格式
});
// typeof result.data => 'object'
// result.data.url => /?a=1&b=2
可以指定类型
import { makeHttpRequest } from '@midwayjs/core';
const result = await makeHttpRequest('http://127.1:7001/', {
method: 'GET',
dataType: 'json',
});
返回 text 格式。
import { makeHttpRequest } from '@midwayjs/core';
const result = await makeHttpRequest('http://127.1:7001/', {
method: 'GET',
dataType: 'text',
});
POST 请求并返回 JSON。
import { makeHttpRequest } from '@midwayjs/core';
const result = await makeHttpRequest('http://127.1:7001/', {
method: 'POST',
data: {
a: 1,
b: 2
},
dataType: 'json',
contentType:'json', // 发送的 post 为 json
});
// result.data ...
注意,请不要在请求中直接返回 result 对象,result 对象是标准的 httpResponse,在大部分场景下无法被直接序列化,会抛出对象循环的错误。
设置请求超时时间。
import { makeHttpRequest } from '@midwayjs/core';
let err;
// 超时会报错,注意 catch
try {
const result = await makeHttpRequest('http://127.1:7001/', {
method: 'GET',
dataType: 'text',
timeout: 500,
});
} catch (e) {
err = e;
}
实例形式
import { HttpClient } from '@midwayjs/core';
const httpclient = new HttpClient();
const result = await httpclient.request('http://127.1:7001/');
// Buffer.isBuffer(result.data) => true
和方法形式参数相同。
import { HttpClient } from '@midwayjs/core';
const httpclient = new HttpClient();
const result = await httpclient.request('http://127.1:7001/', {
method: 'POST',
data: {
a: 1,
b: 2
},
dataType: 'json',
contentType:'json', // 发送的 post 为 json
});
// result.data ...
示例形式,可以复用创建出的对象,并且每次请求,都可以带上一些固定的参数,比如 header。
import { HttpClient } from '@midwayjs/core';
const httpclient = new HttpClient({
headers: {
'x-timeout': '5'
},
method: 'POST',
timeout: 2000
});
// 每次都会带上 headers
const result = await httpclient.request('http://127.1:7001/');
Axios 支持
Midway 包裹了 axios 包,使得在代码中可以简单的使用 axios 接口。
和 axios 的一些关系如下:
- 接口完全一致
- 适配依赖注入写法,完整的类型定义
- 方便实例管理和配置统一
相关信息:
描述 | |
---|---|
可用于标准项目 | ✅ |
可用于 Serverless | ✅ |
可用于一体化 | ✅ |
包含独立主框架 | ❌ |
包含独立日志 | ❌ |
安装依赖
$ npm i @midwayjs/axios@3 --save
或者在 package.json
中增加如下依赖后,重新安装。
{
"dependencies": {
"@midwayjs/axios": "^3.0.0",
// ...
},
}
引入组件
首先,引入 组件,在 configuration.ts
中导入:
import { Configuration } from '@midwayjs/core';
import * as axios from '@midwayjs/axios';
import { join } from 'path'
@Configuration({
imports: [
axios // 导入 axios 组件
],
importConfigs: [
join(__dirname, 'config')
]
})
export class MainConfiguration {
}
然后在业务代码中即可注入使用。
使用默认 Axios 实例
接口和 axios 一致。
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
axios.postForm(url[, data[, config]])
axios.putForm(url[, data[, config]])
axios.patchForm(url[, data[, config]])
使用示例:
import { HttpService } from '@midwayjs/axios';
@Provide()
export class UserService {
@Inject()
httpService: HttpService;
async invoke() {
const url = 'https://midwayjs.org/resource/101010100.json';
const result = await this.httpService.get(url);
// TODO result
}
}
配置默认 Axios 实例
HttpService 实例等价于 axios.create
,所以可以有一些配置参数,这些参数了 axios 本身的参数相同,我们可以在 src/config.default.ts
中配置它。
比如:
export default {
// ...
axios: {
default: {
// 所有实例复用的配置
},
clients: {
// 默认实例的配置
default: {
baseURL: 'https://api.example.com',
// `headers` are custom headers to be sent
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
timeout: 1000, // default is `0` (no timeout)
// `withCredentials` indicates whether or not cross-site Access-Control requests
// should be made using credentials
withCredentials: false, // default
},
}
}
}
更多的参数可以参考 axios global config。
创建不同实例
和其他的服务多实例相同,配置不同的 key 即可。
export default {
// ...
axios: {
default: {
// 所有实例复用的配置
},
clients: {
default: {
// 默认实例
},
customAxios: {
// 自定义实例
}
}
}
}
使用方式如下:
import { HttpServiceFactory, HttpService } from '@midwayjs/axios';
import { InjectClient } from '@midwayjs/core';
@Provide()
export class UserService {
@InjectClient(HttpServiceFactory, 'customAxios')
customAxios: HttpService;
async invoke() {
const url = 'https://midwayjs.org/resource/101010100.json';
const result = await this.customAxios.get(url);
// TODO result
}
}
配置全局拦截器
如果使用的是默认的 Axios 实例,可以如下配置。
import { Configuration, IMidwayContainer } from '@midwayjs/core';
import * as axios from '@midwayjs/axios';
import { join } from 'path';
@Configuration({
imports: [
axios // 导入 axios 组件
],
importConfigs: [
join(__dirname, 'config')
]
})
export class MainConfiguration {
async onReady(container: IMidwayContainer) {
const httpService = await container.getAsync(axios.HttpService);
httpService.interceptors.request.use(
config => {
// Do something before request is sent
return config;
},
error => {
// Do something with request error
return Promise.reject(error);
}
);
}
}
如果要给其他实例配置,可以参考下面的代码。
import { Configuration, IMidwayContainer } from '@midwayjs/core';
import * as axios from '@midwayjs/axios';
import { join } from 'path';
@Configuration({
imports: [
axios // 导入 axios 组件
],
importConfigs: [
join(__dirname, 'config')
]
})
export class MainConfiguration {
async onReady(container: IMidwayContainer) {
const httpServiceFactory = await container.getAsync(axios.HttpServiceFactory);
const customAxios = httpServiceFactory.get('customAxios');
customAxios.interceptors.request.use(
config => {
//...
},
error => {
//...
}
);
}
}
直接使用 Axios
@midayjs/axios
导出了原始的axios
实例,在非应用环境中可以直接使用。
import { Axios } from '@midwayjs/axios';
import { ReadStream, createWriteStream } from 'fs';
import { finished } from 'stream/promises';
async function download(url: string, filename: string) {
const writer = await createWriteStream(filename);
const res = Axios.get<ReadStream>(url, {
responseType: 'stream',
});
res.data.pipe(writer);
await finished(writer);
return res;
}