前端项目怎么与本地代理服务器交互的

新手上路,请多包涵

各位大佬,最近整理笔记,遇到了一个问题,没想明白,还望各位大佬解答,谢谢!

使用代理服务器解决跨域时,代理服务器与服务器之间的直接HTTP协议进行通信,而且服务端交互不存在跨域问题,跨域是浏览器因同源策略对ajax(fetch)的限制,这个我理解,但前端项目与代理服务器间的交互我越理越乱,具体问题如下:

1、前端项目运行在浏览器上,浏览器向代理服务器发送的ajax请求,为啥没有跨域问题?我看资料他们说是代理服务器的端口号与前端项目运行时的端口号是一致的,所以没有跨域问题。但计算机一个端口应该只能运行一个程序吧?在React、Vue项目的webpack里面都使用了 http-proxy-middleware 库,这个库的源码在本地创建了一个nodejs服务器,当我们项目启动起来的时候,这个node.js服务器与我们的前端项目是啥关系,没关系还是包含关系啥的?还是说前端运行项目时只是表明监听对应端口,实际并没有占用,所以可以被代理服务器占用?

2、浏览器使用代理插件whistle好像也能实现请求跨域访问? 电脑internet高级设置也能跨域访问? 这些方式有区别呢?

阅读 4.6k
4 个回答
  1. 同源策略是浏览器的特色;

    服务端、APP 不存在跨域问题(当然也可以自己做类似的限制)。
  2. 被同源策略所限制的是网页;

    浏览器插件的后台页面不受这个限制。
  3. 代理服务器首先是一个服务器,然后才是一个代理;

    这个服务器和它自己的网页当然符合同源策略的所有要求(同域名、同端口、同协议),所以不跨域;
    而不是你上面理解的“端口一致所以不跨域”,(网页通常用 80 或 443 端口,同端口的概率可大了)。
  4. 一个端口当然只能运行一个服务器;

    你可以起多个服务,然后看它们的是否一致,Vue-cli 会从 3000 开始,之后是 3001 、3002……所以端口占用是存在的。
  5. 基本上所有在本地实现跨域的方案都可以总结为:使用不受同源策略限制的软件,帮助网页获取跨域资源

    注意是在本地,也就是不需要目标服务器作任何改动;
    各个方案的不同点就很多了,包括名字都不一样。
  6. 上一条说的是“基本上”,而不是“全部”,因为旧版 chrome 浏览器的同源策略是可以关闭的。

    据说 48 版以后就不能 disable-web-security了,我试了一下手里的 94,确实不管用了。
  1. 一个端口只能运行一个程序狭义理解起来没错,如果你不弄代理,这个端口就被你的Vue/React占用直接本地返回给你静态网页,如果你用了代理服务器,他就会在这个请求基础上跑一个本地服务器,发起代理跨域请求然后把响应传回来。其实用http-proxy-middleware实现跨域和什么"端口号一致"联系不大,主要是因为他跑了一个服务器来发起请求,而不是你浏览器直接发起请求。
  2. whistle印象中也需要本地项目npm引用的来创建代理服务器的,然后再配合插件调用,对这个了解不多。

如果你自己配过代理 你一定会对这个过程更加了解,
你是为了解决跨域问题,所以你的目标请求地址的协议/域名/端口号与你的网页地址不一致,
那么代理服务器的作用就是,让你的网页地址和接口的请求地址一致,这样就解决了跨域的问题,然后代理服务器通过nginx转发 请求真正的目标服务器地址

回到你的问题:计算机一个端口应该只能运行一个程序吧?
是的,一个端口只能运行一个程序,这里你纠结代理服务器的端口号与前端项目运行时的端口号是一样的,给你举个例子:假设前端运行在8054端口,那么代理服务器就不能用8054端口了,那假设就用8055端口,那么为了使前端跟代理服务器同源,要想办法让前端访问页面也使用8055端口,跨域的问题就引刃而解了,可以看我这篇文章nginx解决跨域

我们看一下http-proxy-middleware的用法:

var express = require('express')
var proxy = require('http-proxy-middleware')
 
var app = express()
 
app.use('/api', proxy({ 
    target: 'http://www.example.org',
    changeOrigin: true 
}))
app.listen(3000)
 
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar

这个插件是用于把请求代理转发到其他服务器的中间件,他与前端项目是没有关系的,假设我们当前主机为http://localhost:3000/,现在我们有一个需求,如果我们请求/api,我们不希望由3000来处理这个请求,现在,我们利用express3000端口启动了一个小型的服务器,,使发到3000端口的/api请求转发到了www.example.org上。即请求http://localhost:3000/api相当于请求http://www.example.org/api/foo/bar, 前端运行项目肯定是占用了一个端口,代理服务器也会占用一个端口,使用同一个端口肯定是通过转发代理来达到同源的目的

同样的,修改电脑hosts文件也能跨域访问,配置的内容是

127.0.0.1 ip.you.proxy.com

当你接口访问如 http://127.0.0.1/api/test 时, 会自动访问为http://ip.you.proxy.com/api.test

最后,这些方式都没啥区别,本质上是为了让本地运行的网页跟代理服务器同源,然后代理服务器转发接口

一个网站正常运转需要两种资源:1. 静态资源文件,例如js、css、图片等文件。当你在浏览器地址蓝输入某个网站的域名后,浏览器会向该网站的静态资源服务器请求、并且获取这些静态资源文件;2. 后端api服务数据,也就是从后台数据库读取返回给浏览器的数据。浏览器拿到静态资源文件进行渲染运行时,里面某些js可能会发起Ajax请求,这些Ajax请求可以理解为由浏览器发送给后端api服务器的。

提供静态资源的服务和后台api数据的服务可能存在跨域,例如这两种资源可能放在不同服务器。

webpack配置的devServe本质是让本地提供的静态资源服务器向本地提供的代理服务器发送请求,然后本地提供的代理服务器转发这个请求给真正需要请求的后台api服务器。本地提供的静态资源服务器和本地提供的代理服务器都在本地,协议、地址、端口都是一样的,不存在跨域问题。

推荐问题
宣传栏