如何解决axios请求远程数据会遇到的跨域问题-设置代理

3,823 阅读3分钟

参考网址:

vue cli: cli.vuejs.org/zh/

axios: github.com/axios/axios

安装axios

  1. 在项目文件夹下安装axios npm i axios,举例:

    image.png

  2. 导入并应用axios ,举例:

    // 导入
    import axios from 'axios'
    
    // 应用
    async function getNews(){
    const resp = await axios.get('https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=50&desktop=true')
    }
    getNews();
    
  3. 运行项目 npm run serve

    image.png

  4. 出现 跨域 问题

    image.png

为什么会产生跨域问题

我们目前请求的是前端开发服务器,这个服务器是vue-cli脚手架给我们搭建的,而脚手架是用webpack搭建的。

image.png

浏览器请求前端开发服务器的流程:

  1. 浏览器输入http://localhost:8080/ 请求前端开发服务器

  2. 前端开发服务器返回一个页面

  3. 浏览器渲染页面,查看网页源码发现只有一个js,浏览器就会请求js

    image.png

  4. js里有ajax请求,而我们请求的另外一个服务器,一般来说是后端测试服务器(里面是测试的数据),后端会给一个地址,比如 http://test-data:3000/api/news

  5. 当前页面的访问路径 和 在当前页面中请求的接口如果协议、域名、端口号有一个不一致就会导致跨域,举例:如下,域名和端口号不一致导致了跨域

    当前页面:http://localhost:8080/

    当前页面请求的接口:http://test-data:3000/api/news

  6. 虽然跨域了,但是后端测试服务器还是给了数据,浏览器发现有跨域,为了安全会阻止把数据给js,js拿不到并且会报错,

  7. 所以,开发环境会跨域,而生产环境一般情况下没有跨域

image.png

为什么生产环境没有跨域

真实的情况:

  1. 我们将项目开发好后会进行打包,打包到项目文件夹下的dist目录,里面是纯粹的静态的html文件,比如:js、css,
  2. 这些会上传到服务器上,服务器不仅能托载静态资源,还可以提供api
  3. 等服务器部署好之后,用户只要访问 http://www.my-site.com 就能访问到真实的服务器
  4. 服务器就会给我们一个页面,页面里面有js、css
  5. 拿到js,运行js,js里有ajax请求,请求的还是这个 http://www.my-site.com/api/new ,相同的协议和域名,所以,不产生跨域

image.png

如何解决开发环境的跨域问题

设置代理

浏览器请求数据的流程:

  1. 浏览器请求开发服务器,拿到页面,请求js(此时没有跨域,请求的是localhost)
  async function getNews(){
  const resp = await axios.get('https://localhost:8080/api/')
   }
   getNews();
  1. 开发服务器要设置功能,把它变成代理,当看到这个地址就会转发到后端测试服务器,服务器与服务器之间没有跨域,跨域只有浏览器会产生

  2. 如何设置代理

    (1) 在项目文件根目录下创建配置文件 vue.config.js(这是vue-cli的配置文件)

    module.exports = {
        devServer: {
            proxy: {
                '/api': {
                    target:'https://www.zhihu.com'             
                }
            }
        }
    }
    

    这样就拿到了数据

    image.png

流程图:

  1. 浏览器请求开发服务器,此时没有跨域(地址是http://localhost:8080/.....)

  2. 开发服务器发现它的路径是以"/api"开头

  3. 于是开发服务器把这个请求转发到知乎服务器,开发服务器请求https://www.zhihu.com,路径保持不变

  4. 开发服务器拿到数据后再给浏览器

    image.png

补充

  1. 请求可以省略协议、主机名和端口号,省略协议就用当前网站的协议,主机名和端口号就用当前网页的主机名和端口号

    async function getNews(){
       const resp = await axios.get('/api/v3/feed/topstory/hot-lists/total?limit=50&desktop=true')
    }