Nginx 反向代理解决跨域、Mac配置hosts

Nginx-反向代理解决跨域-Mac配置hosts

Posted by cl9000 on July 14, 2019

Nginx 反向代理解决跨域、Mac配置hosts

Nginx 是一个很强大的高性能Web和反向代理服务。利用好配置文件,将会很方便。Nginx 百度百科

正向代理和反向代理

正向代理的例子:隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都由代理服务器代替来请求。 VPN 就是正向代理
反向代理的例子:反向代理隐藏了真实的服务端

使用node搭建简易服务器

先用node写一个服务接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// index.js
const http = require('http');
const fs = require('fs');
const url = require('url');

const server = http.createServer(function (req, res) {
if (req.url === '/favicon.ico') {
return;
}
const parseUrl = url.parse(req.url, true);
console.log('parseUrl', parseUrl.pathname)
if (parseUrl.pathname === '/api/getData') {
const list = {'id': 1, 'name': '张三'}
res.writeHead(200, {'content-Type':'text/html;charset=UTF-8'})
res.end(JSON.stringify(list))
} else {
res.write(`port: 8088`)
res.end()
}
});
server.listen(8088, function () {
console.log('server is starting on port 8088');
});

执行启动命令:

1
$ node index.js

访问测试一下,测试地址 http://localhost:8088/api/getData
响应返回服务写入测试数据即可,例如:

1
2
3
4
{
"id": 1,
"name": "张三"
}

跨域问题

简易测试接口页面

写一个简易的 ajax 请求页面,用http-server启动访问下,F12查看日志,可以发现请求跨域了:

http-server 启动 访问接口为全地址: http://127.0.0.1:8088/api/getData
Nginx 反向代理 访问接口为相对地址: /api/getData

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
43
44
45
46
47
48
49
50
51
52
<!-- index.html -->
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="referrer" content="never">
<title>测试跨域</title>
<link rel="stylesheet" href="style.css">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">

(function(para){
/* 服务请求 */
// get请求
var SERVER_URL = '';
var ajax = new XMLHttpRequest();
// ajax.open('GET', 'http://t.weather.sojson.com/api/weather/city/101030100');
// ajax.open('GET', '/api/weather/city/101030100', true); // 或 http://localhost:80/api/weather/city/101030100
ajax.open('GET', 'http://127.0.0.1:8088/api/getData', true); // http-server 启动访问
// ajax.open('GET', '/api/getData', true); // Nginx 反向代理
ajax.send();
ajax.onreadystatechange = function() {
if (ajax.readyState == 4 && ajax.status == 200) {
console.log(ajax.responseText);
}
}

// post请求
// var xhr = new XMLHttpRequest();
// xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// xhr.open('post', SERVER_URL + '/api/getData');
// xhr.send('name=233');
// xhr.onreadystatechange = function () {
// if (xhr.readyState == 4 && xhr.status == 200) {
// console.log(xhr.responseText);
// }
// }

console.log('id = ' + para.id);
console.log('name = ' + para.name);
console.log('url = ' + para.url);
})({
id: 13,
name: '张三',
url: 'http://www.bing.com?'
})
</script>
</body>
</html>

浏览器访问测试地址:http://localhost/html5/, 端口是80,可默认不带
跨域问题返回日志:

1
2
Access to XMLHttpRequest at 'http://127.0.0.1:8088/api/getData' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
GET http://127.0.0.1:8088/api/getData net::ERR_FAILED

kuayulog.png

关于跨域的问题一般是由后台添加请求头或CORS进行解决,或Nginx反向代理,前端不需要做额外操作,此处仅为前端单独测试。

使用Mac自带Nginx,或重新单独自定义安装

Mac 自带 Nginx 路径及启动关闭操作命令:

1
2
3
4
5
6
7
8
9
10
/usr/local/bin/nginx    // 符号链接路径
/usr/local/var/www // 默认服务器根目录
/usr/local/etc/nginx // nginx配置目录,nginx配置相关的文件都在这个目录

#启动 nginx
nginx // or: /usr/local/bin/nginx
### 重新加载配置 | 重启 | 停止 |退出
nginx -s reload|reopen|stop|quit
# 测试配置是否有语法错误
nginx -t

nginx.conf配置,配置反向代理

配置代理,下面意思就是我们请求中有 api 这样的就会代理到 http://127.0.0.1:8088,所以我们只要访问 http://localhost:80/api/getData,这个不跨域的接口,然后就会由Nginx截取接口并反向代理到 http://localhost:8088/api/getData

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
      listen       80;
server_name localhost,test2.com;

#charset koi8-r;
#access_log logs/host.access.log main;

location / {
root html;
index index.html index.htm;
}

location ^~ /html5 {
alias /Users/weichanglu/Desktop/Login;

# HTML5 History 模式配置
try_files $uri $uri/ /html5/index.html;
#index index.html;
}

# URL重写 仅将 /api 下的url反向代理到后端地址
location ^~ /api {
# rewrite ^/api/(.*)$ /$1 break; ## /api/xxx 改为 /xxx
proxy_pass http://127.0.0.1:8088; # 转发地址
# proxy_pass http://t.weather.sojson.com;
}

配置好之后需要重启一下 Nginx 服务,执行一下重启命名即可。若有问题,可先停掉 Ngix,再重新启动。
若 80 端口不可用,可换用其它端口,或者清掉Mac自带 Apache 的80端口
查看Nginx占用进程: $ ps aux | grep nginx

验证跨域的解决

使用 Nginx 需要把 ajax 请求的接口换成相对地址,如下:

1
2
3
4
// ajax.open('GET', 'http://t.weather.sojson.com/api/weather/city/101030100');
// ajax.open('GET', '/api/weather/city/101030100', true);
// ajax.open('GET', 'http://127.0.0.1:8088/api/getData', true);
ajax.open('GET', '/api/getData', true);

浏览器重新访问测试一下,地址 http://localhost/html5/
现在就不会在有跨域的问题了。

自定义域名,本地测试,修改hosts文件

Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应网页,如果没有找到,则系统会再将网址提交DNS域名解析服务器进行IP地址的解析。 hosts 百度百科

Nginx添加测试域名、修改hosts文件

在Nginx中添加自定义测试域名,并重启 Nginx

1
2
3
4
5
6
7
8
9
10
listen       80;
server_name localhost,test2.com;

#charset koi8-r;
#access_log logs/host.access.log main;

location / {
root html;
index index.html index.htm;
}

Mac hosts文件路径(command + shift + G 快速前往文件夹)
/etc/hosts

注意:host文件是个文本编辑文稿类型!!!需要复制到外部编辑完后,在进行验证替换即可生效,若不生效,后面或有清理 Chrom 浏览器的DNS链接方法。

编辑 hosts 文件,参考其它新增一行:
127.0.0.1 test2.com
为了验证是否生效,可以再新增一行:
127.0.0.1 www.taobao.com
替换掉源文件后,浏览器输入 https://www.taobao.com/,看是否还可以访问,不能正常访问说明已经生效。(验证完即可删除,否则原网站不可访问)

测试域名地址: http://test2.com/html5/,正常访问,说明已生效

若hosts文件并不生效

Chrome浏览器输入:chrome://net-internals/#dns
选择 DNS Host resolver cache 点击下 Clear host cache
chrome-dns.png

再重新访问:
http://test2.com/html5/ 正常访问,说明已生效

https://www.taobao.com/ 不能正常访问说明已经生效。(验证完即可删除,否则原网站不可访问)

旧方法

  • CORS 全称Cross-Origin Resource Sharing,是HTML5规范定义的如何跨域访问资源。
    服务端进行设置CORS策略
    Access-Control-Allow-Origin: http://test.com
    Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS
    Access-Control-Max-Age: 86400
  • JSONP通常以函数调用的形式返回
    需要首先在页面中准备好回调函数,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<p id="jsonp"></p>
<button onclick="getData()" style="width: 100px;height: 45px;">刷新请求</button>

// 提前准备好的回调方法
function refreshPrice(data) {
var p = document.getElementById('jsonp');
p.innerHTML = '股票当前价格:' + data['0000001'].name +': ' + data['0000001'].price + ';' + data['1399001'].name + ': ' + data['1399001'].price;
}
// 触发函数
function getData() {
var js = document.createElement('script'),
head = document.getElementsByTagName('head')[0];
js.src = 'http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice';
head.appendChild(js);
}

这就完成了跨域加载数据。建议主要用于测试,
跨域一般后台进行解决 CORS

参考

https://zhuanlan.zhihu.com/p/94197713
修改Hosts为何不生效,是DNS缓存?



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!