抽丝剥茧:详述一次DevServer Proxy配置无效问题的细致排查过程

本文主要是介绍抽丝剥茧:详述一次DevServer Proxy配置无效问题的细致排查过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

事情的起因是这样的,在一个已上线的项目中,其中一个包含登录和获取菜单的接口因响应时间较长,后端让我尝试未经服务转发的另一域名下的新接口,旧接口允许跨域请求,但新接口不允许本地访问(只允许发布测试/生产的域名访问)。

问题

那么问题来了,本地环境该如何成功访问到新的接口并验证业务功能是否生效呢?

在这里插入图片描述

尝试过程

我首先就想到了直接在 webpack 项目中配置 devServer,并且修改接口地址(为了安全隐私,隐去公司实际域名,使用 xxxxx 来替代。)

devServer: {proxy: {'/': {target: 'https://xxxxx.cn',pathRewrite: {'/proxyApi': '',},changeOrigin: true,},},
} 

但返回的接口提示【登录态无效】,这下起码不跨域了!本来以为已经代理成功,只需要找到后端看看报错即可。

在这里插入图片描述

但后端反馈这个报错是因为请求头没有携带指定参数,他也查不到该请求的详细信息。这时候我又开始有疑问了,明明查看请求头是有的呀。

在这里插入图片描述

疑问

在 chrome 浏览器上看到的请求地址并不是后端提供的真实接口请求地址,而是加了我代理的字段。在响应体上我也没有找到 location 等字段反馈到真实的请求接口。

此时的我怀疑,代理是真的生效了吗,我请求的接口是真实的后端接口吗?开始验证 devServer 的 proxy 是否执行。在 proxy 处配置请求前后输出的函数,结果发现 onProxyReq 和 onProxyRes 都没有执行。

proxy: {'/proxyApi': {target: 'https://xxxxx.cn',pathRewrite: {'/proxyApi': '',},changeOrigin: true,onProxyReq(proxyReq, req, res) {console.log('>>>请求', req);},onProxyRes(proxyRes, req, res) {// 响应的钩子函数console.log('>>>响应', res);},},
},

所以此时猜测是不是整个 devServer 都没有生效,但如何证明它没有生效呢?

证实

目前代理后端域名不受我们控制,我无从知晓它是否发送到后端服务器上,所以我打算自己用 nodejs 开启一个服务,开启服务的方式很简单,使用核心模块 https 几行代码搞定。

const http = require("http");const server = http.createServer((req, res) => {console.log(">>req", req.url, req.rawHeaders );res.end("hello");
});server.listen("3002", () => {console.log("3002端口启动了");
});

通过 node 启动服务后,首先验证是否可拦截请求,直接通过浏览器窗口 输入 localhost:3002

在这里插入图片描述

哎~ 服务启动了,页面也得到的响应,服务器能获取到刚刚 get 请求的数据

在这里插入图片描述

此时将项目中 proxy 的配置改为 3002 端口的服务,再次执行业务逻辑代码发送请求,发现此时3002端口启动的服务控制台空空如也!也就是说,它根本没有拦截到该请求。

proxy: {'/proxyApi': {target: 'http://localhost:3002',
},

猜想是否因为项目里的接口请求工具导致无法拦截,于是直接在页面上使用 fetch 发送请求,此时发现 3002 端口的服务仍然没有接收到请求。

fetch('https://xxxxx.cn/proxyApi/yyyyy/operateTargetNew')

本来以为是不是 proxy 字符匹配的问题,因为 /proxyApi 标识出现在整个url 中间,试图修改为正则表达式 "**/proxyApi/*",也是无效的

proxy: {'**/proxyApi/*': {
},

再次尝试

这时候我意识到一个问题,带有域名的接口访问好像不行,那我直接去掉域名呢?

此时直接使用 fetch 请求不包含域名的接口地址

fetch('/proxyApi/yyyyy/operateTargetNew')

这个时候,终于看到了问题即将解决的曙光!调用接口成功获取到了 3002 端口返回的响应。

在这里插入图片描述

也能在本地的 3002 端口服务上获取到请求的详细信息。在这里插入图片描述

拨开云雾

查询资料发现果然是接口地址的原因。Webpack DevServer的proxy配置主要用于开发环境中,针对的是由本地DevServer发出的API请求。

当你在前端代码中发送请求时,通常会使用相对路径(如/api/xxx/yyy),这样它们就会被发送到当前页面所在的主机和端口,也就是Webpack DevServer。

这时,DevServer的proxy设置可以将请求转发到配置的后端服务器。

// webpack.config.js
module.exports = {// ...devServer: {proxy: {'/api': {target: 'http://your-backend-server.com',changeOrigin: true,},},},
};

现在,如果你发送一个请求到/api/xxx/yyy,DevServer会将它代理到http://your-backend-server.com/api/xxx/yyy。

然而,如果你在前端代码中直接使用了完整的URL(即包含域名https://www.xxxx.com/api/xxx/yyy),就绕过了Webpack DevServer,请求直接发往该完整URL对应的服务器。DevServer的proxy配置不会和这个请求交互,因此无法将它代理到你配置的目标服务器。

请求改造

于是再改回需要代理的接口,并对项目逻辑进行一些改造,因为默认的网络库会拼接url,这里做一个判断,将需要代理的域名和代理的字符作为一组值保存起来。

如果匹配中需要代理的需求,并用前缀来替换。

// 本地环境,需要将代理的接口剔除域名,并拼接代理前缀if (process.env.NODE_ENV === 'development') {const proxyObj = {'https://xxxx.cn': '/proxyApi',};const proxyKeys = Object.keys(proxyObj);for (let i = 0; i < proxyKeys.length; i++) {const host = proxyKeys[i];if (option.url.includes(host)) {const prefix = proxyObj[host];option.url = option.url.replace(host, prefix);}}}

这样就可以将接口请求拼接为 https://xxxx.con 域名的全部替换为指定前缀,这样这部分的请求就都会走代理。

在这里插入图片描述

很惭愧,虽然早就知道 webpack 的 proxy 配置解决本地跨域问题,但确实很少自己去配置,一般是后端解决掉跨域问题或者项目里的自带里处理方案,所以真正到自己配置的时候多少有点迷糊了。

这篇关于抽丝剥茧:详述一次DevServer Proxy配置无效问题的细致排查过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/984427

相关文章

本地搭建DeepSeek-R1、WebUI的完整过程及访问

《本地搭建DeepSeek-R1、WebUI的完整过程及访问》:本文主要介绍本地搭建DeepSeek-R1、WebUI的完整过程及访问的相关资料,DeepSeek-R1是一个开源的人工智能平台,主... 目录背景       搭建准备基础概念搭建过程访问对话测试总结背景       最近几年,人工智能技术

MySQL的cpu使用率100%的问题排查流程

《MySQL的cpu使用率100%的问题排查流程》线上mysql服务器经常性出现cpu使用率100%的告警,因此本文整理一下排查该问题的常规流程,文中通过代码示例讲解的非常详细,对大家的学习或工作有一... 目录1. 确认CPU占用来源2. 实时分析mysql活动3. 分析慢查询与执行计划4. 检查索引与表

MySQL报错sql_mode=only_full_group_by的问题解决

《MySQL报错sql_mode=only_full_group_by的问题解决》本文主要介绍了MySQL报错sql_mode=only_full_group_by的问题解决,文中通过示例代码介绍的非... 目录报错信息DataGrip 报错还原Navicat 报错还原报错原因解决方案查看当前 sql mo

Spring Boot 整合 ShedLock 处理定时任务重复执行的问题小结

《SpringBoot整合ShedLock处理定时任务重复执行的问题小结》ShedLock是解决分布式系统中定时任务重复执行问题的Java库,通过在数据库中加锁,确保只有一个节点在指定时间执行... 目录前言什么是 ShedLock?ShedLock 的工作原理:定时任务重复执行China编程的问题使用 Shed

Linux部署jar包过程

《Linux部署jar包过程》文章介绍了在Linux系统上部署Java(jar)包时需要注意的几个关键点,包括统一JDK版本、添加打包插件、修改数据库密码以及正确执行jar包的方法... 目录linux部署jar包1.统一jdk版本2.打包插件依赖3.修改密码4.执行jar包总结Linux部署jar包部署

MYSQL事务死锁问题排查及解决方案

《MYSQL事务死锁问题排查及解决方案》:本文主要介绍Java服务报错日志的情况,并通过一系列排查和优化措施,最终发现并解决了服务假死的问题,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录问题现象推测 1 - 客户端无错误重试配置推测 2 - 客户端超时时间过短推测 3 - mysql 版本问

Git提交代码详细流程及问题总结

《Git提交代码详细流程及问题总结》:本文主要介绍Git的三大分区,分别是工作区、暂存区和版本库,并详细描述了提交、推送、拉取代码和合并分支的流程,文中通过代码介绍的非常详解,需要的朋友可以参考下... 目录1.git 三大分区2.Git提交、推送、拉取代码、合并分支详细流程3.问题总结4.git push

Linux内存泄露的原因排查和解决方案(内存管理方法)

《Linux内存泄露的原因排查和解决方案(内存管理方法)》文章主要介绍了运维团队在Linux处理LB服务内存暴涨、内存报警问题的过程,从发现问题、排查原因到制定解决方案,并从中学习了Linux内存管理... 目录一、问题二、排查过程三、解决方案四、内存管理方法1)linux内存寻址2)Linux分页机制3)

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

VScode连接远程Linux服务器环境配置图文教程

《VScode连接远程Linux服务器环境配置图文教程》:本文主要介绍如何安装和配置VSCode,包括安装步骤、环境配置(如汉化包、远程SSH连接)、语言包安装(如C/C++插件)等,文中给出了详... 目录一、安装vscode二、环境配置1.中文汉化包2.安装remote-ssh,用于远程连接2.1安装2