🌒 实现处理请求 head
# 需求分析
要支持发送请求的数据类型,需要支持配置 headers
的属性来调整 content-type
。如下:
axios({
method: 'post',
url: '/base/post',
headers: {
'content-type': 'application/json;charset=utf-8'
},
data: {
a: 1,
b: 2
}
})
2
3
4
5
6
7
8
9
10
11
并且在当传入的 data
为普通对象的时候, headers
如果没有配置 Content-Type
属性,需要自动设置请求 header
的 Content-Type
字段为: application/json;charset=utf-8
。
# processHeader
函数实现
创建文件 src/helpers/headers.ts
实现处理请求头工具函数:
import { isPlainObject } from './util'
function normalizeHeaderName(headers: any, normalizedName: string): void {
if (!headers) return
Object.keys(headers).forEach(name => {
if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
headers[normalizedName] = headers[name]
delete headers[name]
}
})
}
export function processHeaders(headers: any, data: any): any {
normalizeHeaderName(headers, 'Content-Type')
if (isPlainObject(data)) {
if (headers && !headers['Content-Type']) {
headers['Content-Type'] = 'application/json;charset=utf-8'
}
}
return headers
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
由于
header
属性的key
是大小写不 in 干的,例如之前穿入的header
属性名content-type
是全小写的,所以要先把header
属性名先处理规范化。然后在添加
header
。
# 在入口文件添加请求 header
处理逻辑
首先需要先修改 AxiosRequstConfig
接口类型的定义,要添加 headers
可选属性:
在 src/types/index.ts
:
export interface AxiosRequestConfig {
url: string
method?: Method
data?: any
params?: any
headers?: any
}
2
3
4
5
6
7
在 src/index.ts
中添加处理 header
逻辑:
function processConfig(config: AxiosRequestConfig): void {
config.url = transformURL(config)
config.headers = transformRequestHeader(config)
config.data = transformRequestData(config)
}
// ...
function transformRequestHeader(config: AxiosRequestConfig): any {
const { headers = {}, data } = config
return processHeaders(headers, data)
}
2
3
4
5
6
7
8
9
10
11
12
注意,因为处理 header
时,依赖了 data
,所以处理请求 body
数据之前处理请求 header
。
在 src/xhr.ts
:
import { AxiosRequestConfig } from './types'
export default function xhr(config: AxiosRequestConfig) {
const { data = null, url, method = 'get', headers } = config
const request = new XMLHttpRequest()
request.open(method.toUpperCase(), url, true)
Object.keys(headers).forEach(name => {
if (data === null && name.toLowerCase() === 'content-type') {
delete headers[name]
} else {
request.setRequestHeader(name, headers[name])
}
})
request.send(data)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在使用 XMLHttpRequest
的实例时,添加额外的判断传入 data
为空的时候,请求 header
配置 Content-Type
是没有意义的,所以将它删除。
# 编写测试 DEMO
在上一节处理 body
参数的基础上,添加 headers
的 content-type
类型:
axios({
method: 'post',
url: '/base/post',
data: {
a: 1,
b: 2
}
})
axios({
method: 'post',
url: '/base/post',
headers: {
'content-type': 'application/json'
},
data: {
a: 1,
b: 2
}
})
const paramsString = 'q=URLUtils.searchParams&topic=api'
const searchParams = new URLSearchParams(paramsString)
axios({
method: 'post',
url: '/base/post',
data: searchParams
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
测试可以看到,没有添加
headers
的content-type
,检测到请求数据是普通数据也会为其添加;同时当data
为某些类型如URLSearchParams
时,浏览器会自动为请求header
添加合适的Content-Type
。