GET请求拦截,添加自定义头部

1,756 阅读1分钟

一、背景

前端需要对多有的get请求增加自定义的header头以满足业务场景的的需要,目前客户端前端有浏览器和小程序。

二、常见的get请求场景

  1. 静态资源src,如img、video等
  2. form表单get请求
  3. 打开新页面,如a标签、location.href
  4. XMLHttpRequest封装,如ajax,axios等

三、拦截方式

  1. 静态资源src,如img、video等 可以通过Window.customElements自定义标签的方式。继承原有属性的基础上,使用CustomElementRegistry.define()进行扩展。以img标签为例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Proxy Image</title>
    <script>
        let requestImage = function (url, element) {
            let request = new XMLHttpRequest();
            request.responseType = 'blob';
            request.open('get', url, true);
            request.setRequestHeader('Authorization', '身份凭证');
            request.onreadystatechange = e => {
                if (request.readyState == XMLHttpRequest.DONE && request.status == 200) {
                    element.src = URL.createObjectURL(request.response);
                    element.onload = () => {
                        URL.revokeObjectURL(element.src);
                    }
                }
            };
            request.send(null);
        }
 
        class AuthImg extends HTMLImageElement {
            constructor() {
                super();
                this._lastUrl = '';
            }
 
            static get observedAttributes() {
                return ['authSrc'];
            }
 
            connectedCallback() {
                let url = this.getAttribute('authSrc');
                if (url !== this._lastUrl) {
                    this._lastUrl = url;
                    requestImage(url, this);
                }
                console.log('connectedCallback() is called.');
            }
        }
 
        window.customElements.define('auth-img', AuthImg, {extends: 'img'});
    </script>
</head>
<body>
<img width="100" height="100" is="auth-img"
     authSrc="http://threex.top/images/image_201909111450326.jpg">
</body>
</html>
  1. 针对form表单get请求,原生的form表单无法实现,需要xhr模拟提交。一般业务上通过组件库,使用xhr进行提交,可暂不考虑

  2. 打开新页面,如a标签、location.href,通过chrome插件可以实现,无法在业务上使用。

  3. XMLHttpRequest封装,如ajax,axios等。

    vue + axios项目中 业务上通常在axios.interceptors拦截中作统一的请求头处理。

    axios.interceptors.request.use((config) => {
      const authStore = useAuthStore();
      config.headers['Authorization'] = '身份凭证';
      return config;
    });
    

    也可以对XMLHttpRequest原型send方法进行处理

    let req = XMLHttpRequest;
    (function(open, send) {
      XMLHttpRequest.prototype.open = function() {
        open.apply(this, arguments); 
      }
      XMLHttpRequest.prototype.send = function () {
        this.setRequestHeader('Authorization', '身份凭证')
        send.apply(this, arguments); 
      }
    })(req.prototype.open, XMLHttpRequest.prototype.send)
    

四、结论

目前浏览器尚且不能覆盖所有场景,小程序等应用端更是不支持。等架构师那边把思路打开,看下能不能另辟蹊径。

五、参考文档

1. CustomElementRegistry

2. CustomElementRegistry/define

3. 如何给img标签里的请求添加自定义header