zoukankan      html  css  js  c++  java
  • React axios 使用 http-proxy-middleware 解决跨域问题小记

    壹 ❀ 引

    在上篇bug分析的记录文中,提到axios可做到取消接口请求,所以想写一篇关于axios.CancelToken使用以及原理分析的文章(主要是自己好奇到底如何做到的取消)。在准备工作阶段,我需要在本地写一个发起请求的demo并模拟取消,这样才便于例子分析和理解。但在本地react demo运行的过程中遇到了跨域问题,解决跨域的过程中,也被一些错误的文章所误导,占用了一些时间,因此此篇文章主要详细记录react使用axios如何解决跨域问题(其实跟axios也没啥关系),那么本文开始。

    贰 ❀ 开始准备

    我的react demo是基于Create React App,这里就不提怎么安装了,具体可参考官方文档或者从零开始的react入门教程(一),让我们从hello world开始一文。于是乎我在终端执行了npm install axios安装 axios

    由于我们需要请求一个接口,方便后续的请求展示,我顺手在百度输入了接口测试,于是找到了getman,点击了确认了按钮,打开控制台发现发起了一个请求https://getman.cn/api/request,那么我们也来请求这个地址好了。

    于是我在index.js中定义了一个简单的组件,代码如下:

    import React, {
      Component
    } from 'react';
    import ReactDOM from 'react-dom';
    import axios from 'axios';
    
    class Parent extends Component {
      componentDidMount() {
        // 我们也来获取这个地址
        axios.get('https://getman.cn/api/request')
          .then((res) => {
            console.log(res)
          })
          .catch((err) => {
            console.log(err)
          })
      }
      render() {
        return (
          <div>你好,echo。</div>
        );
      }
    }
    
    ReactDOM.render(
      <Parent />,
      document.getElementById('root')
    );
    
    

    npm start运行项目发现报错,看错误信息就知道是跨域了,毕竟我们本地协议以及端口http://localhost:3001/都跟需要请求的地址完全不同。那么就开始着手解决跨域吧,网上也有一些方案,折腾了一番,这里我们使用代理来解决。

    叁 ❀ http-proxy-middleware解决跨域

    我们需要额外下载一个三方包http-proxy-middleware,在编辑器终端直接执行npm install http-proxy-middleware --save进行安装。安装完毕后,在src目录下新建文件setupProxy.js,具体配置如下:

    const {createProxyMiddleware} = require('http-proxy-middleware');
    module.exports = function(app) {
      app.use(createProxyMiddleware('/api', 
        {
            "target": "https://getman.cn",
            "changeOrigin": true,
        }))
    }
    

    注意,一定是const {createProxyMiddleware} = require('http-proxy-middleware')而不是const proxy = require('http-proxy-middleware'),很多人的博客都是用后面这句,如果这么那就是疯狂报错,完全没效果....

    然后回到我们的index.js,修改请求地址的那一句代码为:

    // 原代码为
    // axios.get('https://getman.cn/api/request')
    // 修改为
    axios.get('api/request')
    

    保存,刷新页面,你会发现跨域报错已经不存在,而控制台也成功展示了我们请求拿回来的接口数据。

    简单解释下这段配置,代理它到底帮我们做了什么。我们可以把本地跑起来的服务理解为用户A,A发起请求,希望去自己所在的服务(我们当前运行的本地项目)的api/request路径下找一个东西,很明显我们项目中没有这个路径,所以常规来说请求http://localhost:3001/api/request一定报404

    此时来了个代理商B,他跟我们本地服务A说,你把你要请求的地址告诉我,我帮你转发,帮你访问到你真正想要访问的信息。而我们本地可以发起N种请求,哪些要代理哪些不要代理呢?因此A和B约定了,只要你的请求带有/api,我就帮你转发,转发到哪呢?转发到https://getman.cn

    于是A请求了api/request,B发现这个地段里面有/api,于是就去https://getman.cn的目录下找,找什么呢?找api/request,所以最终转发的地址就是https://getman.cn + api/request,所以顺利请求了https://getman.cn/api/request

    createProxyMiddleware后的第一个字段,更像是一个约定,同时也是代理商去target寻找的第一级目录,比如我们把代码修改成如下:

    // index.js修改为
    axios.get('request')
    // 配置修改为
    module.exports = function(app) {
      app.use(createProxyMiddleware('/request', 
        {
            "target": "https://getman.cn/api",
            "changeOrigin": true,
        }))
    }
    

    上述修改中,前端请求request,其实也就是要到服务端request目录下拿个东西,于是代理监听到了,就去https://getman.cn/下找,那这样肯定找不到,所以我们在target进行了手动补全,自己在默认加了/api,这样就成了https://getman.cn/api + request,重新运行项目,你发现也成功请求了。

    打开控制台查看我们请求的地址其实是http://localhost:3000/request,但事实上代理帮我们转发,实际访问的是另一个地址,大概如此了。

  • 相关阅读:
    Spring Boot分布式系统实践【扩展1】shiro+redis实现session共享、simplesession反序列化失败的问题定位及反思改进
    Spring Boot分布式系统实践【2】框架搭建
    javascript日期比较 js日期相差天数计算
    SyntaxHighlighter_代码高亮插件
    CSS控制div自动延伸到窗口100%高度
    iphone天气插件weathericon,安装,及其解决天气不变的方法!亲测!
    Zapatec.Calendar 说明文档
    html设置多少秒跳转
    CSS命名规范
    解决firefox的button按钮文字不能垂直居中
  • 原文地址:https://www.cnblogs.com/echolun/p/15173956.html
Copyright © 2011-2022 走看看