qs.stringify()的疑问
来源:9-4 合并配置的设计与实现 - flatten headers + demo 编写

慕粉1470117225
2020-07-14
老师,qs.stringify()将对象序列化成URL的形式,然后content-type就会变成application/x-www-form-urlencoded,这是为啥啊
// `data` 是作为请求主体被发送的数据
// 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
// 在没有设置 `transformRequest` 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: {
firstName: 'Fred'
},
写回答
2回答
-
许愿瓶啊
2020-08-21
这个是默认headers的配置,代码如下:
const methodsWithData = ['post', 'put', 'patch'] methodsWithData.forEach(method => { (defaults.headers as any)[method] = { 'Content-Type': 'application/x-www-form-urlencoded' } })
注意这里是在 header 的 post 属性上挂载的,还有一个地方会定义 content-type,代码如下:
export function processHeaders(headers: HttpHeaders, data: any): HttpHeaders { normalizeHeaderName(headers, 'Content-Type') if (isPlanObject(data)) { if (headers && !headers['Content-Type']) { headers['Content-Type'] = 'application/json;charset=utf-8' } } return headers }
这里判断用户没有定义content-type,并且 data 是纯对象的话就会在 header 上挂载 content-type
最关键的合并策略代码如下:
export function flattenHeaders(headers: any, method: Method): any { if (!headers) { return } headers = deepMerge(headers.common, headers[method], headers) const methodsDelete = ['delete', 'get', 'head', 'options', 'post', 'put', 'patch', 'common'] methodsDelete.forEach(method => { delete headers[method] }) return headers }
这里会有一个优先级的问题,deepMerge 的合并会依次遍历并挂载属性,所以属性相同的情况下后面的对象会覆盖前面对象的属性,这里的优先级关系是:
直接挂载在 header 上的属性最牛!
其次是各种方法定义的属性
最后是公共属性
这样写也非常的合理,所以这里的 data 如果是纯对象的话会直接挂载在 headers 上,优先级最高,application/json;charset=utf-8
会覆盖了 post 属性上的 application/x-www-form-urlencoded,如果不是的话就会用默认的 application/x-www-form-urlencoded00 -
ustbhuangyi
2020-07-14
你可以打个断点调试一下,在发送请求前,看看 request header 有哪些。
00
相似问题