写在前面

传送门

项目全局配置,这个是接口请求和登录请求的host

1
2
3
4
module.exports={
apiHost: "//ssppre.adbaitai.com",//接口apihost
loginApiHost: "//ssppre.adbaitai.com"//登录和apiHost区分出来主要是本地代理无法处理登录问题
};

而这个项目的预发host是ssppre.adbaitai.com

我本地通过Nginx配合hosts绑定,做了一个反向代理,将h6.ssppre.adbaitai.com,代理到http://localhost:8084

这样做的目的是想在本地能够调用预发的登录接口,如果不做这层代理的话,直接http://localhost:8084打开项目是种不上登录的cookie的,因为跨域

做到这一步应用是成功登录了,但是后续的一些接口请求是报错的,因为我本地是h6.ssppre.adbaitai.com,而apiHost是//ssppre.adbaitai.com。

同样还是跨域问题,现在要做的是对接口的调用进行代理

1
2
3
4
module.exports={
apiHost: "//h6.ssppre.adbaitai.com",//接口apihost
loginApiHost: "//ssppre.adbaitai.com"//登录和apiHost区分出来主要是本地代理无法处理登录问题
};

如上,将apiHost改成本地的,然后再将Nginx改一下

将带有api 的请求都进行拦截,然后走ssppre.adbaitai.com

这样就解决了本地调试跨域问题

但是,我这几天自己在搭一个博客系统的时候发现这个方法行不通了

纳尼😱,试了很多次都是404(因为之前的方法可以是后端已经做了cors的处理,所以直接拦截api就可以实现代理)

很多人觉得不应该是报跨域的错吗,然而并没有,是404

为什么会出现404,很显然,这是代理成功了,也请求到了我的接口,而且我接口日志中也有请求日志,既然请求到了为什么会是404,原因就是,你请求我,但是我不想给你数据

解决这个问题的方法有两种(我喜欢用的两种):

1.我后台是koa2搭的,所以我引入了一个插件—koa2-cors

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const Koa = require('koa');
const fs = require('fs');
const config = require('./config/default.js');
// const cors = require('koa2-cors');
const middlewares = require('./middlewares/middlewares.js');
const app = new Koa();
// 具体参数我们在后面进行解释
app.use(cors({
origin: function (ctx) {
if (ctx.url === '/test') {
return "*"; // 允许来自所有域名请求
}
return 'http://youstde.blog.com'; // 这样就能只允许localhost:8080 这个域名的请求了
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}));

const main = async ctx => {
// ctx.cookies.set(
// 'cid',
// 'helloworld',
// {
// domain: '127.0.0.1',
// path: '/',
// maxAge: 10 * 60 * 1000,
// expires: new Date('2017-02-15'), // cookie失效时间
// httpOnly: false, // 是否只用于http请求中获取
// overwrite: false // 是否允许重写
// }
// );
//单页面应用的话,这个方法只会执行一次
}
// app.use(require('./routers/article.js').routes());
app.use(require('./routers/sign.js').routes());
app.use(middlewares);
app.listen(config.port,()=>{
console.log(`app is listenning on ${config.port}`);
});

配置一下corse,这样之前的404就变成了200了

2.Nginx的反向代理

不是之前的那种做法,只是做api的拦截,然后重定向到指定地址

是给接口地址新开一个Nginx配置

至此,接口也从飘红的404变成了绿色的200了,很开心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
server  {
listen 80;
server_name youstde.blog.com;

location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_set_header Connection "";
proxy_pass http://localhost:8080;

}
}
server {
listen 80;
server_name api.youstde.blog.com;

location / {
add_header 'Access-Control-Allow-Origin' 'http://youstde.blog.com';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_set_header Connection "";
proxy_pass http://localhost:7001;

}

}

补充两点:

1.路径重写

1
2
3
4
5
location ^~/cross_origin/ {
#重写路径
rewrite ^/cross_origin/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:7001/;
}

location配置的意思是对包含 “cross_origin” 请求拦截,并对请求路径进行重写,一开始请求路径是
“/cross_origin/get_json?type=20170126” ,重写后便成了
“/get_json?type=20170126”,$1代表(.)中的内容,而(.)则代表 cross_origin
后面的全部字符,也就是我们会把 cross_origin 部分去掉,但是保留 cross_origin 之后的所有字符

2.反向代理的时候的POST请求

我用的是axios去做请求处理,但是发送post请求的时候出现了这个情况

很显然是发送了一个预请求,因为不是一个简单的请求

首先我们得了解什么是简单请求和非简单请求

文章看这里

而且关于axios中如何去设置

看这里