夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • TypeScript基础

  • TypeScript进阶

  • TS 从零实现 axios

    • 初识 TypeScript

    • TypeScript 常用语法

    • ts-axios 项目初始化

    • ts-axios 基础功能实现

      • 处理请求 url 参数
      • 处理请求 body 数据
      • 处理请求 header
        • 需求分析
        • processHeaders 函数实现
        • 实现请求 header 处理逻辑
        • demo 编写
      • 获取响应数据
      • 处理响应 header
      • 处理响应 data
    • ts-axios 异常情况处理

    • ts-axios 接口扩展

    • ts-axios 拦截器实现

    • ts-axios 配置化实现

    • ts-axios 取消功能实现

    • ts-axios 更多功能实现

    • ts-axios 单元测试

    • ts-axios 部署与发布

  • 《TypeScript》
  • TS 从零实现 axios
  • ts-axios 基础功能实现
HuangYi
2020-01-05
目录

处理请求 header

# 处理请求 header

# 需求分析

我们上节课遗留了一个问题:

axios({
  method: 'post',
  url: '/base/post',
  data: {
    a: 1,
    b: 2
  }
})
1
2
3
4
5
6
7
8

我们做了请求数据的处理,把 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
  }
})
1
2
3
4
5
6
7
8
9
10
11

并且在当我们传入的 data 为普通对象的时候,headers 如果没有配置 Content-Type 属性,需要自动设置请求 header 的 Content-Type 字段为:application/json;charset=utf-8。

# processHeaders 函数实现

根据需求分析,我们要实现一个工具函数,对 request 中的 headers 做一层加工。我们在 helpers 目录新建 headers.ts 文件。

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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

这里有个需要注意的点,因为请求 header 属性是大小写不敏感的,比如我们之前的例子传入 header 的属性名 content-type 就是全小写的,所以我们先要把一些 header 属性名规范化。

# 实现请求 header 处理逻辑

在这之前,我们先修改一下 AxiosRequestConfig 接口类型的定义,添加 headers 这个可选属性:

types/index.ts

export interface AxiosRequestConfig {
  url: string
  method?: Method
  data?: any
  params?: any
  headers?: any
}
1
2
3
4
5
6
7

index.ts:

function processConfig (config: AxiosRequestConfig): void {
  config.url = transformURL(config)
  config.headers = transformHeaders(config)
  config.data = transformRequestData(config)
}

function transformHeaders (config: AxiosRequestConfig) {
  const { headers = {}, data } = config
  return processHeaders(headers, data)
}
1
2
3
4
5
6
7
8
9
10

因为我们处理 header 的时候依赖了 data,所以要在处理请求 body 数据之前处理请求 header。

xhr.ts:

export default function xhr (config: AxiosRequestConfig): void {
  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)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

这里要额外判断一个逻辑,当我们传入的 data 为空的时候,请求 header 配置 Content-Type 是没有意义的,于是我们把它删除。

# demo 编写

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
})
1
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
29

通过 demo 我们可以看到,当我们请求的数据是普通对象并且没有配置 headers 的时候,会自动为其添加 Content-Type:application/json;charset=utf-8;同时我们发现当 data 是某些类型如 URLSearchParams 的时候,浏览器会自动为请求 header加上合适的 Content-Type。

至此我们对于请求的处理逻辑暂时告一段落。目前我们的请求从网络层面是可以收到服务端的响应的,下一节课我们就从代码层面来处理服务端响应,并且让调用方可以拿到从服务端返回的数据。

编辑 (opens new window)
#TypeScript
上次更新: 2022/6/27 21:52:41
处理请求 body 数据
获取响应数据

← 处理请求 body 数据 获取响应数据→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式