第一次用uni.request请求后端接口时,看到控制台报错"Access-Control-Allow-Origin"的时候,我整个人都是懵的。明明Postman能正常调用的接口,为什么在H5页面就报错?后来才明白这是浏览器的同源策略在作祟。
现代前端开发基本都是前后端分离架构,前端跑在localhost:3000,后端API在api.yourdomain.com。浏览器出于安全考虑,默认禁止这种跨域请求。而在UniApp打包成App或小程序时,其实没有这个限制,问题就出在H5环境——它本质上就是个网页。
我见过不少新手开发者的"野路子"解决方案:有的让后端直接关闭CORS校验(安全隐患极大),有的改用JSONP(现在很多API已不支持),还有的甚至要求用户手动关闭浏览器安全设置(简直离谱)。其实在开发阶段,最简单的方案就是配置devServer的proxy。
打开你的manifest.json文件,找到(或新建)h5节点。这里有个坑要注意:一定要切换到"源码视图"才能修改,可视化编辑器是看不到完整配置项的。配置模板长这样:
json复制"h5": {
"devServer": {
"proxy": {
"/api": {
"target": "https://your-real-api.com",
"changeOrigin": true,
"secure": false
}
}
}
}
我来拆解下这几个关键参数:
配置完后,当你在代码里调用:
javascript复制uni.request({
url: '/api/user/list'
})
实际发出的请求会自动变成https://your-real-api.com/api/user/list,完美绕过浏览器同源限制。不过这里有个常见坑点:修改manifest.json后必须重新运行项目才会生效,HBuilderX的热更新对配置文件无效。
很多老项目API设计不规范,路径里根本没有统一前缀。比如你可能遇到这种情况:
/user/info/product/list这时候就需要pathRewrite出场了。改造后的配置示例:
json复制"proxy": {
"/proxy_api": {
"target": "https://your-real-api.com",
"pathRewrite": {
"^/proxy_api": ""
}
}
}
这样配置后:
/proxy_api/user/infohttps://your-real-api.com/user/infopathRewrite的本质是正则替换,我常用这些骚操作:
"^/api/v1" : "/api""^/dev" : "/prod""^/user/(.*)" : "/api/v2/user/$1"真实项目往往需要区分开发/测试/生产环境。我推荐这种目录结构:
code复制├── config
│ ├── dev.js
│ ├── test.js
│ └── prod.js
└── manifest.json
然后在manifest.json中动态引入配置:
javascript复制const config = require('./config/' + process.env.NODE_ENV)
"proxy": {
"/api": {
"target": config.apiBaseUrl
}
}
开发中还会遇到这些典型问题:
"cookieDomainRewrite": "localhost"ws: trueheaders字段注入"secure: false"临时跳过验证实测过程中我发现HBuilderX有个小坑:修改proxy配置后,有时需要完全退出重启才能生效。建议每次修改后:
很多人以为proxy是uniapp的黑魔法,其实底层用的是webpack-dev-server的能力。当你在本地启动开发服务器时:
http://localhost:8080/api/data/api开头的请求整个过程浏览器始终只和本地服务器通信,根本不知道有跨域这回事。这也是为什么proxy方案仅适用于开发环境,生产环境要么需要后端配CORS,要么通过Nginx反向代理。
问题1:配置了proxy但请求还是报跨域错误
问题2:POST请求变成OPTIONS
问题3:接口返回404但Postman能通
问题4:HTTPS证书验证失败
"secure: false"再次强调:devServer.proxy只是开发工具!线上环境需要这些方案:
方案A:Nginx反向代理
nginx复制location /api/ {
proxy_pass https://your-api-server.com/;
proxy_set_header Host $host;
}
方案B:后端开启CORS
java复制// Spring Boot示例
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("*");
}
};
}
方案C:云服务商API网关
最近在做一个电商项目时,就遇到了第三方支付接口的跨域问题。由于对方服务器无法修改CORS配置,最终我们采用了Nginx中转方案,在测试环境用proxy,生产环境用Nginx,完美实现了开发和生产配置的无缝切换。