什么是代理,node&nginx前端代理详解

一. 什么是代理?

代理就是通过一个特殊的网络服务去访问另一网络服务的一种间接访问方式。像我们不能直接访问国外的网站,只能使用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;
}

说明:

  1. 使用 root 时, 服务器里真实的资源路径是 root 的路径拼接上 location 指定的路径
  2. 使用alias顾名思义是代指 location 的别名, 不论location 是什么, 资源的真实路径都是alias所指定的,所以location是匹配浏览器输入的地址, 真实访问的路径就是alias 指定的路径
  3. 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-For
        proxy_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错误

### 前端开发中代理模式的实现与应用 #### 什么是代理模式? 代理模式是一种结构型设计模式,其核心思想是通过创建一个中间层来间接访问某个对象。这种模式允许开发者在不改变原始对象的情况下,在访问该对象之前或之后加入额外逻辑[^1]。 #### 代理模式的作用 在前端开发中,代理模式通常被用来拦截对目标对象的操作并附加功能。常见的用途包括但不限于: - 数据缓存:减少重复计算或网络请求。 - 权限验证:确保只有授权用户才能调用某些方法。 - 日志记录:跟踪函数调用的历史以便调试或分析。 - 性能优化:延迟加载资源直到真正需要时才获取。 #### ES6 Proxy 的动态代理实现 ES6 中引入了 `Proxy` 对象,它是现代 JavaScript 实现代理模式的一种强大工具。`Proxy` 可以监听和拦截几乎所有的操作行为(如属性读取、赋值、枚举等),从而轻松实现复杂的代理逻辑。 下面是一个简单的例子,展示如何利用 `Proxy` 创建一个具有日志记录功能的对象: ```javascript const targetObject = { name: 'Alice', age: 25, }; // 使用 Proxy 包裹目标对象 const handler = { get(target, prop) { console.log(`Accessing property "${prop}"`); return Reflect.get(target, prop); }, set(target, prop, value) { console.log(`Setting property "${prop}" to ${value}`); return Reflect.set(target, prop, value); } }; const proxyObject = new Proxy(targetObject, handler); proxyObject.name; // 输出 Accessing property "name" proxyObject.age = 30; // 输出 Setting property "age" to 30 ``` 上述代码展示了如何通过 `get` 和 `set` 方法分别捕获属性访问和修改事件,并打印相应的日志消息。 #### 静态代理的简单实现 除了动态代理外,还可以采用静态代理的方式手动定义代理类或者函数。这种方式适用于场景较为固定的情况。例如: ```javascript function Target() {} Target.prototype.request = function () { console.log('Handling request.'); }; function StaticProxy(targetInstance) { this.target = targetInstance; } StaticProxy.prototype.request = function () { console.log('Before handling...'); this.target.request(); console.log('After handling...'); }; const target = new Target(); const staticProxy = new StaticProxy(target); staticProxy.request(); // 执行前置处理 -> 调用原方法 -> 后置处理 ``` 此示例说明了如何构建一个围绕现有服务实例运行的静态代理。 #### 学习意义 掌握代理模式不仅有助于提高程序的功能灵活性,还能促进良好的编码习惯形成。正如所提到,“设计模式是对特定问题的有效解答”,它们代表了一套已经被证明有效的策略集合[^3]。因此熟悉这些经典模型能够显著改善个人技术水平以及团队协作效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值