什么是代理,nodenginx前端代理详解
一. 什么是代理?
代理就是通过一个特殊的网络服务去访问另一网络服务的一种间接访问方式。像我们不能直接访问国外的网站,只能使用VPN,就是使用了代理
二. 前端为什么要用代理?
首先明确以下两个概念
(1)前端应用要能访问,那必须是放在服务器上(服务器可以是nginx、nodejs、apache、tomcat等),像我们本地vue开发就是用nodejs启动了一个服务。
(2)由于浏览器的同源策略(协议、ip、端口号都相同为同源),禁止网站向非同源的服务器发送ajax异步请求,也就是跨域。
明白以上两点就知道我们本地开发要调用服务器的接口,就会跨域。解决跨域的手段有很多种,像是cors、jsonp等,但是他们都有缺陷,代理是前端解决跨域的终极手段。
浏览器 | 代理服务器 | 后端服务器 |
---|---|---|
本地node 或者nginx |
三.代理的使用
node.js
node.js的本地web服务搭建
1. 初始化项目
npm init
2. 安装express(基于Node.js 平台,快速、开放、极简的Web开发框架)
npm install express
3. 新建一个文件夹,把前端打包的资源放里面
4. 在index.js中引入静态文件
// 导入express模块
const express = require('express')
// 创建express服务实例
const app = express()
// 静态资源
app.use(express.static(__dirname+'/html'))
// app.use("/", express.static('./html'))
app.use("/h5", express.static('./h5/html'))
5. http-proxy-middleware 代理中间件
安装http-proxy-middleware
npm install http-proxy-middleware
6.导入
// 导入 http-proxy-middleware代理中间件
const { createProxyMiddleware } = require("http-proxy-middleware");
7.配置
app.use("/api",createProxyMiddleware({target:'https://***.**.net', // 目标服务器地址pathRewrite:{'^/api': '/testapi', // 重写路径},changeOrigin: true, // 默认是false 是否需要改变原始主机头为目标url})
)
8. 其他配置
const history = require('connect-history-api-fallback')
// connect-history-api-fallback防止history模式下页面刷新404,它将把请求定位到你指定的索引文件(默认为 /index.html)const bodyParser = require("body-parser")
//设定文件上传大小const log4js = require('log4js')
//请求日志
9.完整的index.js文件
// 导入express模块
const express = require('express')
// history模式防止404
const history = require('connect-history-api-fallback')
// 导入日志
const log4js= require('./log-config')
const logger = log4js.getLogger()
// 导入 http-proxy-middleware代理中间件
const { createProxyMiddleware } = require("http-proxy-middleware");
// 文件大小中间件
const bodyParser = require("body-parser");
// 接口上下文
const context = "/api";
// 创建express服务实例
const app = express()
app.use(history())
// 静态资源
app.use(express.static(__dirname+'/html'))
// app.use("/", express.static('./html'))
app.use("/h5", express.static('./h5/html'))// 上传文件大小
app.use(bodyParser.json({limit:'5000kb'}))
app.use(bodyParser.urlencoded({limit:'5000kb',extended:true}))
// app.use(express.json({limit:'5000kb'}))// 打印日志
log4js.useLogger(app,logger)app.use(context,createProxyMiddleware({target:'https://***.***.net', // 目标服务器地址pathRewrite:{'^/api': '/testapi', // 重写路径},changeOrigin: true, // 默认是false 是否需要改变原始主机头为目标url})
)
// 端口号,超时时间
app.listen(5005,(err)=>{if(!err){console.log('启动成功')}
}).setTimeout(500000)
四.Nginx
1. 官网下载 https://nginx.org/en/download.html
说明:下载后的nginx文件夹路径上不能有中文,否者无法启动nginx
2. 把打包后的前端文件放到html文件夹下面
3. Nginx的配置文件conf/nginx.conf
说明:nginx配置文件内行尾要加分号,不能有中文空格
4. 配置前端静态文件请求
location / {root html/dist;index index.html index.htm;try_files $uri $uri/ /index.html;
}
location /h5/ {root html;index index.html index.html;try_files $uri $uri/ /h5/index.html;
}location /web/ {alias html/h5/;# index index.html index.html;try_files $uri $uri/ /h5/index.html;
}
说明:
- 使用 root 时, 服务器里真实的资源路径是 root 的路径拼接上 location 指定的路径
- 使用alias顾名思义是代指 location 的别名, 不论location 是什么, 资源的真实路径都是alias所指定的,所以location是匹配浏览器输入的地址, 真实访问的路径就是alias 指定的路径
- try_files $uri $uri/ /index.html; 解决页面刷新404
5. 配置接口代理
location /api {proxy_redirect off; #关闭重定向proxy_set_header Host $host;# $host浏览器请求的ip,$http_host 浏览器请求的ip和端口号,$proxy_host 被代理服务的ip和端口号proxy_set_header X-Real-IP $remote_addr; # 前一节点ip(非用户真实IP)proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #前一节点X-Forwarded-Forproxy_pass https://***.***.net/testapi;}
注意点
通过nginx访问https:// * . * .net /api/ login来说明情况
-
location和proxy_pass后都不加斜杠
location /api {proxy_pass https://***.***.net;}
实际访问地址为https://* * . * *.net /api/login
-
location加proxy_pass不加
location /api/ {proxy_pass https://***.***.net;}
实际访问地址为https://* * . * *.net /api/login
-
location和proxy_pass都加
location /api/ {proxy_pass https://***.***.net/;}
实际访问地址为https://* * . * *.net /login
-
location不加proxy_pass加
location /api {proxy_pass https://***.***.net/;}
实际访问地址为https://* * . * *.net /login
- 总结:
只要是proxy_pass 端口后方加了斜杠的那么 location都会被替换,不会加到实际访问路径中,包括( proxy_pass
https://* * . * *.net/testapi;)也算
6. 其他
client_max_body_size 限制请求体的大小,若超过所设定的大小,返回413错误
client_header_timeout 读取请求头的超时时间,若超过所设定的大小,返回408错误
client_body_timeout 读取请求实体的超时时间,若超过所设定的大小,返回413错误