8-1、axios其他功能实现

1、withCredentials

修改类型定义:

interface AxiosRequestConfig {
  // ...
  withCredentials?: boolean
export default function xhr(config: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    // method和data可能没有, 所以给出默认值
    const {
      method = 'get',
      data = null,
      headers,
      responseType,
      timeout,
      cancelToken,
      withCredentials
    } = config
     // ...
    if (withCredentials) {
      request.withCredentials = withCredentials
2、CSRF防御

CSRF的防御手段有很多,比如验证请求的referer,但是referer是可以伪造的,所以杜绝此类攻击的一种方式是服务器要求每次请求都包含一个token,这个token不在前端生成,而是在我们每次访问站点的时候生成,并通过set-cookie的方式保存在客户端,然后客户端发送请求的时候,从cookie中对应的字段独处token,然后添加到请求headers中。这样服务器就可以从请求headers中读取这个token并验证。由于这个token是很难伪造的,所以就能区分这个请求是否是用户正常发起的。

对于我们的ta-axios库,我们要自动把这几件事做了,每次发送请求的时候,从cookie中读取对应的token值,然后添加到请求headers中。我们允许用户配置xsrfCookieName表示存储token的cookie名称,xsrfHeaderName表示请求headers中token对应的header名称。

axios.get('/more/get',{
  xsrfCookieName: 'XSRF-TOKEN', // default
  xsrfHeaderName: 'X-XSRF-TOKEN' // default
}).then(res => {
  console.log(res)

我们提供xsrfCookieName和xsrfHeaderName的默认值,当然用户也可以根据自己的需求在请求中去配置xsrfCookieName和xsrfHeaderName。

interface AxiosRequestConfig {
  //...
  xsrfCookieName?: string,
  xsrfHeaderName?: string
  • 修改默认配置
  • const defaults: AxiosRequestConfig = {
      // ...
      xsrfCookieName: 'XSRF-TOKEN',
      xsrfHeaderName: 'X-XSRF-TOKEN'
    

    接下来我们要做3件事
    1、首先判断如果配置withCredentials为true或者是同源请求,我们才会在请求headers中添加xsrf相关字段;
    2、如果判断成功,尝试从cookie中读取xsrf的token值;
    3、如果能读到,则把它添加到请求headers的xsrf的相关字段中。

    helpers/url.ts
    interface URLOrigin {
      protocol: string,
      host: string
    const urlParsingNode = document.createElement('a')
    const currentOrigin = resolveURL(window.location.href)
    function resolveURL(url: string): URLOrigin {
      urlParsingNode.setAttribute('href', url)
      const { protocol, host } = urlParsingNode
      return {
        protocol,
    function isURLSameOrigin(requestURL: string): boolean {
      const parsedOrigin = resolveURL(requestURL)
      return currentOrigin.protocol === parsedOrigin.protocol && currentOrigin.host === parsedOrigin.host
    
  • cookie获取
    cookie.ts
  • const cookie = {
      read(name: string): string | null {
        const match = document.cookie.match(new RegExp('(^|;\s*)(' + name + ')(=[^;]*)'))
        return match ? decodeURIComponent(match[3]) : null
    export default cookie
    

    修改xhr.ts

    export default function xhr(config: AxiosRequestConfig): AxiosPromise {
      return new Promise((resolve, reject) => {
        const {
           // ...
          xsrfCookieName,
          xsrfHeaderName
        } = config
        //...
        if ((withCredentials || isURLSameOrigin(url!)) && xsrfCookieName) {
          const xsrfValue = cookie.read(xsrfCookieName)
          headers[xsrfHeaderName!] = xsrfValue
        // ...
    
    import axios, { Canceler } from '../../src/index'
    const instance = axios.create({
      xsrfCookieName: 'XSRF-TOKEN-D',
      xsrfHeaderName: 'X-XSRF-TOKEN-D'