后端项目组在内部搭建的YAPI上设计接口文档,前端项目组要进行模拟测试,由于YAPI上的接口分组是以数字ID进行区分的,这就导致,如果有多个数据来源,那么前端项目组要么自己写逻辑判断该调用哪个接口,要么测试的时候分开配置,显然这两项工作前端小组做不太愿意,那么就使用NGINX将多个请求地址统一一下或许是个好办法。
需求:
原YAPI接口地址1:http://192.168.10.10/mock/100+$接口请求路径(如:http://192.168.10.10/mock/100/user/list)
原YAPI接口地址2:http://192.168.10.10/mock/201+$接口请求路径(如:http://192.168.10.10/mock/201/info/list)
需要将访问地址合并:http://192.168.10.12/mock/api +$接口请求路径
(其中100,201是YAPI项目代号)
于是,爬坑开始。。nginx rewrite,porxy_pass 各种测试,原来想采用if 判断请求地址该去哪个路由,然后设置到变量里,但这种做法失败了,于是开始采用接口贪婪匹配的方法,结果就是要写很多行location。
开始使用rewrite 重定向到新的接口,随之的问题就是 get 请求一般没问题,但post 的时候由于是302跳转,所以会丢失请求的参数。前端采用vue同时也遇到访问跨域问题,以下通过事件一并说明解决方法:
遇到的问题:
1:请求是确定的get 还是get/post 不确定?
由于后端开发标准不一致,有时是get,有时是post,他们总喜欢按自己的方式来,可能如果细化get/post会增加工作量吧。
方案:所以我遇到的问题是,不清楚到底是哪种请求,所以nginx里的 location 路由方案就是 proxy_pass,而不是rewrite;
小坑:用rewirte对于get请求,是没有问题的,但是遇到post就会丢失数据,因为是302跳转,没有二次提交post;
2:关于nginx的 '/' 路径问题
由于开始没有明白nginx的匹配机制,匆忙实践,导致这个坑必须有;
列:
原访问地址:http://192.168.10.10/mock/100/user/list
新访问地址:http://192.168.10.10/mock/api/user/list
location /mock/api/user/ {
proxy_pass http://192.168.10.10/mock/100/api/;
proxy_set_header Host 192.168.10.10;
proxy_set_header X-Forwarded-For $remote_addr;
}
原访问地址:http://192.168.10.10/mock/201/info/list
新访问地址:http://192.168.10.10/mock/api/info/list
location /mock/api/info/ {
proxy_pass http://192.168.10.10/mock/201/api/;
proxy_set_header Host 192.168.10.10;
proxy_set_header X-Forwarded-For $remote_addr;
}
其中 location /mock/api/info/ 是普通匹配,也可以采用正则匹配,本来想想用另一种参数方法来实现只写一个 location
但失败了,
===============================================================
失败案例如下:
location /mock/api/ {
set $newuri '';
if ( $request_uri ~* /mock/api/user/ ) {
set $newuri '100';
}
if ( $request_uri ~* /mock/api/info/ ) {
set $newuri '201';
}
proxy_pass http://192.168.10.10/mock/$newuri/api/ ;
proxy_set_header Host 192.168.10.10;
proxy_set_header X-Forwarded-For $remote_addr;
}
但是这种做法无法正常运作,可能是没搞清楚nginx 机制,知道的道友,提点一二;
================================================================
反向代理(proxy_pass)的地址,如果最后有 '/',
如:proxy_pass http://192.168.10.10/mock/100/api/;
请求 http://192.168.10.12/mock/api/user/list ;
真实:http://192.168.10.10/mock/100/user/list
如果没有'/':,
如:proxy_pass http://192.168.10.10/mock/100/api;
请求 http://192.168.10.12/mock/api/user/list ;
真实:http://192.168.10.10/mock/api/mock/100/user/list
3: 跨域问题
由于前端采用的是vue.js实现,所有跨域其实有两个问题;
1:nginx的跨域设置
解决:nginx.conf配置
server {
listen 80;
server_name 192.168.10.12;
access_log logs/192.168.10.12.access.log;
root D:/wwwroot/192.168.10.12;
index index.php default.php index.html index.htm default.html default.htm;
include rewrite/192.168.10.12conf;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
error_page 403 /403.html;
error_page 404 /404.html;
error_page 502 /502.html;
location /mock/api/user/ {
proxy_pass http://192.168.10.10/mock/100/api/;
proxy_set_header Host 192.168.10.10;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /mock/api/info/ {
proxy_pass http://192.168.10.10/mock/201/api/;
proxy_set_header Host 192.168.10.10;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
关键是在配置中加入:
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
采用postman进行访问测试,正常!但用vue项目访问,仍然出现跨域问题;于是看下面的解决方案;
2:vue的跨域代理访问
解决:
前提,nginx的跨域访问正常。
vue:在webpack的配置文件设置代理接口访问属性
webpack 项目目录 config/index.js
proxyTable: {
'/mock/api/':{
target:'http://192.168.10.12/',
changeOrigin: true,
pathRewrite: {
'^/mock/api': '/mock/api'
}
}
}
意思就是,如何本地是采用localhost启动的测试,就是把请求发送到代理地址去解析;
访问 http://localhost/mock/api/user/list 实际:http://192.168.10.12/mock/api/user/list
这样vue的跨域问题不会出现了。
-------------------------------
以上花了整整1天多解决,走了很多弯路,这就是没系统学过nginx直接上手必须要经历的坑。