处理request body遗留的问题
axios({
method: 'post',
url: '/base/post',
data: {
a: 1,
b: 2
}
})
我们做了请求数据的处理,把data转换成了json字符串,但是服务端并不能正确解析出我们发送的数据。这是因为我们没有在header中设置正确的Content-Type,所以我们需要在发送请求的时候,支持配置headers属性,如下:
axios({
method: 'post',
url: '/base/post',
headers: {
'content-type': 'application/json;charset=utf-8'
},
data: {
a: 1,
b: 2
}
})
并且在传入普通json对象并且没有设置Content-Type时,默认Content-Type: 'application/json;charset=utf-8'
那么接下来我们来实现processHeaders函数
src/helpers/headers
import { isPlainObject } from "./util";
function normalizeHeaderName(headers: any, normalizedName: string): void {
if (!headers) {
return
}
Object.keys(headers).forEach(name => {
if (name.toLowerCase() === normalizedName.toLowerCase() && name !== normalizedName) {
headers[normalizedName] = headers[name]
delete headers[name]
}
})
}
function processHeaders(headers: any, data: any): any {
// 因为headers中的属性名是大小写不敏感的,所以我们需要对headers中的属性规范化
normalizeHeaderName(headers, 'Content-Type')
// 如果data为空,那么设置'Content-Type'是没有意义的,这里删除它
if (!data) {
if (headers && headers['Content-Type']) {
delete headers['Content-Type']
}
return headers
}
if (isPlainObject(data)) {
if (!headers) {
headers = {
'Content-Type': 'application/json;charset=utf-8'
}
return headers
}
if (!headers['Content-Type']) {
headers['Content-Type'] = 'application/json;charset=utf-8'
}
}
return headers
}
export {
processHeaders
}
src/index.ts
import { AxiosRequestConfig } from "./types";
import xhr from './xhr'
import { buildUrl } from "./helpers/url";
import { transformRequest } from "./helpers/data";
import { processHeaders } from "./helpers/headers";
export default function axios(config: AxiosRequestConfig) {
processConfig(config)
xhr(config)
}
function processConfig(config: AxiosRequestConfig): void {
config.url = tranformUrl(config)
config.headers = transformHeaders(config)
config.data = transformRequestData(config)
}
function tranformUrl(config: AxiosRequestConfig): string {
const { url, params } = config
return buildUrl(url, params)
}
function transformRequestData(config: AxiosRequestConfig): any {
return transformRequest(config.data)
}
function transformHeaders(config: AxiosRequestConfig): any {
const { headers = {}, data } = config
return processHeaders(headers, data)
}
src/xhr.ts
import { AxiosRequestConfig } from "./types";
export default function xhr(config: AxiosRequestConfig): void {
// method和data可能没有, 所以给出默认值
const { url, method = 'get', data = null, headers } = config
const request = new XMLHttpRequest()
request.open(method.toUpperCase(), url)
Object.keys(headers).forEach((name) => {
request.setRequestHeader(name, headers[name])
})
request.send(data)
}
编写demo
import axios from '../../src/index'
axios({
method: 'post',
url: '/api/base/post',
data: {
a: 1,
b: 2
}
})
axios({
method: 'post',
url: '/api/base/post',
data: {
a: 1,
b: 2
}
})
axios({
method: 'post',
url: '/api/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: '/api/base/post',
data: searchParams
})
const arr = new Int32Array([21, 31])
axios({
method: 'post',
url: '/api/base/buffer',
data: arr
})
通过 demo 我们可以看到,当我们请求的数据是普通对象并且没有配置 headers 的时候,会自动为其添加 Content-Type:application/json;charset=utf-8;同时我们发现当 data 是某些类型如 URLSearchParams 的时候,浏览器会自动为请求 header加上合适的 Content-Type。
至此我们对于请求的处理逻辑暂时告一段落。目前我们的请求从网络层面是可以收到服务端的响应的,下一节课我们就从代码层面来处理服务端响应,并且让调用方可以拿到从服务端返回的数据。
网友评论