利用nginx反代实现跨域

一、前言

  我们知道跨域在前端开发中是一个非常常见的问题,我们平时也有很多方法去解决他,比如说降域、cors、jsonp、postMessage等。还有一种很常用的方式是用nginx反代的方式去实现跨域,今天我们就来谈一谈关于使用nginx反代来实现跨域的问题。

二、原理

  我们都知道,跨域问题的产生是因为不同源的问题,那么,同源是指什么呢?同源,即域名、协议、端口都一样即同源。如果有一个不一样则不同源。而浏览器为了安全,对不同源的请求做了限制,即不允许发一个非同源的请求。这里需要划重点:浏览器为了安全。这个意思就是,这个行为是浏览器的行为,而不是你发一个不同源的请求就会被拦截。那么这个问题就好解决了,我们把请求发送到nginx上,在由nginx发送到目的服务器,目的服务器处理完毕后,同样把消息在发送给nginx,nginx在返回给前端。我们在服务器的层面上去处理跨域的问题,就不存在跨域的限制了。

三、实现

  如何在本地配置nginx这里我就不介绍了,如果不了解的同学可以先上网找一找相关的内容学习一下,下面我们先一步步实现。首先先用node在本地搭一个简单的服务器:

var http = require('http');

var hostName = '127.0.0.1';

var port = 8080;

var server = http.createServer(function(req, res) {
    res.setHeader('Content-Type', 'application/json');
    res.end(JSON.stringify('hello'));
});

server.listen(port, hostName, function() {
    console.log(`服务器已启动: ${hostName}:${port}`);
})

  这样,我们就在本地的8080端口起了一个简单的服务器,我们可以尝试一下:
利用nginx反代实现跨域_第1张图片
  下面我们再写一个简单的页面,然后用ajax去请求hello数据。


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Documenttitle>
head>
<body>
    <script>
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4 && xhr.status === 200) {
                console.log(xhr.responseText);
            }
        }
        xhr.open("GET", "localhost:8080", true);
        xhr.send();
    script>
body>
html>

  不出意外的,请求失败了:
在这里插入图片描述
  这个报错就是典型的跨域问题,那么,我们下面想办法解决这个问题。
  首先,我们要让这个请求变成同源的请求,即我们需要让他们的端口相同。

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       8888; # 任意
        server_name  localhost; 

		location / {
			proxy_pass http://localhost:5501/client.index.html;
		}
		
    }

}

  这是nginx的配置文件,看不懂的同学不要紧,我们只需要关注核心部分,即server。listen表示我们的nginx是在端口8888上启动的,location /表示它会拦截localhost:8888这个请求,proxy_pass表示它会将这个请求转发到后面的url上去。最后的效果是什么呢?我们来看一下:
在这里插入图片描述
  我们访问8888端口就可以访问到原来在5001端口上的网页,可是这里还是出现了跨域问题,因为他们的端口还是不一样,下面我们把ajax请求的地址改一下,改成同源请求。

let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
    if(xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
}
xhr.open("GET", "api/getMessage", true);
xhr.send();

  修改后的代码如上所示,此时我们肯定还是不能正常接受到请求的,因为我们在8888端口上根本没有写其他的代码,我们再修改一下nginx配置文件

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       8888; # 任意
        server_name  localhost; 

		location / {
			proxy_pass http://localhost:5501/client/index.html;
		}
	
		location /api/getMessage {
			proxy_pass http://localhost:8080;
		}
	
    }

}

  我们将/api/getMessage的请求转发到8080端口的服务器上,这样就能正常请求数据了。我们启动nginx,然后打开网页看看效果:
在这里插入图片描述
  此时,我们已经正常请求到了数据,而我们的网页和api接口是在两个端口上的。所以这样,我们就利用nginx来实现了跨域的效果。

四、总结

  其实,在这里我们的网页、api接口、nginx分别在三个端口上。其实我们可以把nginx和网页放在一个端口上。那么我们为什么要这么做呢?因为为了更好的理解nginx是如何实现跨域的。只要在浏览器请求的url和自己的url是同源的,那么浏览器就不会对其作出限制。所以,我们将请求都转发到了nginx上,这样我们的各种请求都变成同源的了。至于真实的地址,就由nginx来进行转发,然后返回结果。好了,如果还有不理解的同学可以自己慢慢配一遍,相信你就能理解为什么nginx反代能实现跨域了。

你可能感兴趣的:(前端学习,nginx,跨域)