Nginx 解决请求跨域 与 配置 gzip 压缩

目录

搭建跨域请求环境

Nginx 解决跨域

配置 gzip 压缩

nginx 常用命令


关于什么是跨域?可以参考《JavaScript 跨域请求解决方式汇总》,本文只介绍如何使用 Nginx 解决跨域请求。

搭建跨域请求环境

1、解决跨域之前,先还原一个跨域请求的场景,之后再通过 Nginx 来解决跨域。

2、提供一个简单的 HelloWorld 应用,浏览器访问后进入主页  index.jsp 如下:http://192.168.1.20:8080/HelloWorld/。(192.168.1.20是本机的IP地址,所有的操作都是本机中模拟)

Nginx 解决请求跨域 与 配置 gzip 压缩

3、然后再提供一个应用来访问上面的 HelloWorld 应用,这里直接在 webStorm 中通过 js 中的 ajax 来请求,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title></title>
    <script src="https://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $("button").click(function () {
                $.ajax({
                    url: "http://192.168.1.20:8080/HelloWorld/",
                    success: function (data) {
                        console.log("success:" + JSON.stringify(data));
                    },
                    error: function (data) {
                        console.log("error:" + JSON.stringify(data));
                    }
                });
            });
        });
    </script>
</head>
<body>
<button type="button" style="font-size: 20px">跨域请求</button>
</body>
</html>

Nginx 解决请求跨域 与 配置 gzip 压缩

已拦截跨源请求:同源策略禁止读取位于 http://192.168.1.20:8080/HelloWorld/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

4、从 http://192.168.1.20:55555/liaisonStation/test2.html 的 js 中去请求 http://192.168.1.20:8080/HelloWorld/ ,这是典型的端口不同而导致的跨域请求被同源策略限制。

5、其它解决跨域的方式可以参考《JavaScript 跨域请求解决方式汇总》,这里只介绍使用 Nginx 。

Nginx 解决跨域

1、现在开始通过配置 nginx.conf 来解决上面的跨域问题,为了方便,这里选择在 windows 系统上操作,Linux 系统同理。

2、没有下载安装 Nginx 的可以参考《Nginx》。修改  nginx.conf 配置文件如下:

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


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

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        #本虚拟主机域名,多个时使用空格隔开,默认为 localhost,修改为跨域请求目标的域名,如 www.w3school.com.cn
        server_name  192.168.1.20;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        #设置哪些域名可以跨域请求此虚拟主机,因为从 js 中请求 nginx 时,本身也是跨域请求
        # "*" 表示允许所有的 "源" 进行请求,也可指定只允许某个具体的源可以访问
        add_header Access-Control-Allow-Origin *;
        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass   http://192.168.1.20:8080; #反向代理
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

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


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

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

}

在默认的基础上,修改了第 37、44、48 行。

1)第 37 行:因为页面直接请求 HelloWorld 时被同源策略限制了,于是现在页面请求nginx代理服务器,代理服务器代理 HelloWorld,所以 nginx 虚拟主机的域名(server_name)应该和目标服务器 HelloWorld 的域名一致。

2)而且源(本例为 55555端口的应用)的端口、HelloWorld 的端口以及 Nginx 监听的端口(listen) 可以全部都不同。(本例源是 55555 端口,Nginx 监听的是 80 端口,目标服务器的 8080 端口)

3)因为一个 server 下可以有多个 location,所以也可以配置多个 server_name,空格隔开。

3、start .\nginx.exe 启动 nginx.exe 。显然如果代理成功,此时浏览器输入 http://localhost/HelloWorld/ 也要能访问原来的 http://localhost:8080/HelloWorld/ 才对。

Nginx 解决请求跨域 与 配置 gzip 压缩

4、修改源 55555 端口的应用 js 中的 url 地址:

...
$.ajax({
    //不再直接请求目标服务器,而是请求代理服务器
    url: "http://localhost:80/HelloWorld/",
    success: function (data) {
        console.log("success:" + JSON.stringify(data));
    },
    error: function (data) {
        console.log("error:" + JSON.stringify(data));
    }
});	
...

5、直接停止 nginx : .\nginx.exe -s stop,然后再次启动:start .\nginx.exe,现在进行跨域问题已经解决:

Nginx 解决请求跨域 与 配置 gzip 压缩

配置 gzip 压缩

Nginx 解决请求跨域 与 配置 gzip 压缩

1、GZIP 是规定的三种标准 HTTP 压缩格式之一,对于文本文件,GZip 的效果非常明显,开启后传输所需流量大约会降至 1/4 ~ 1/3

2、目前绝大多数的网站都在使用 GZIP 传输 HTMLCSSJavaScript 等资源文件,主流的浏览器也都支持 gzip 压缩,可以通过请求头中的 Accept-Encoding 查看浏览器支持的压缩类型

Nginx 解决请求跨域 与 配置 gzip 压缩

随便打开一个网站,即可以在请求头中看到 Accept-Encoding(接受编码).

3、启用 gzip 压缩需要客户端和服务端同时支持,如果客户端支持 gzip 解析,那么只要服务端能够返回 gzip 的文件就可以启用gzip了, 可以通过 nginx 的配置来让服务端支持 gzip。

4、如下所示为请求本机应用中的 http://localhost/HelloWorld/jquery-3.4.0.js 文件,默认情况下显然它是没有压缩的。没有压缩时响应头中会有 Content-Length:***,压缩后响应头中会有 Content-Encoding:***

Nginx 解决请求跨域 与 配置 gzip 压缩

5、下面使用 nginx 反向代理目标服务器,然后在 nginx.conf 配置 gzip 压缩:

...
    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    gzip                    on;
    gzip_http_version       1.1;        
    gzip_comp_level         5;
    gzip_min_length         100;
    gzip_types text/csv text/xml text/css text/plain text/javascript application/javascript application/x-javascript application/json application/xml;

    server {
        listen       80;
        #本虚拟主机域名,多个时使用空格隔开,默认为 localhost,修改为跨域请求目标的域名,如 www.w3school.com.cn
        server_name  192.168.1.20;

        #charset koi8-r;
...

gzip:开启或者关闭 gzip 模块,默认值为 off,可配置为 on / off

gzip_http_version:启用 GZip 所需的 HTTP 最低版本,默认值为HTTP/1.1

gzip_comp_level:压缩级别,级别越高压缩率越大,当然压缩时间也就越长(传输快但比较消耗 cpu),默认值为 1,压缩级别取值为1-9。

gzip_min_length:设置允许压缩的页面最小字节数,Content-Length 小于该值的请求将不会被压缩,默认值 0。当设置的值较小时,压缩后的长度可能比原文件大,建议设置 1000 以上(这里是故意降低了阀值)。

gzip_types:要采用 gzip 压缩的文件类型 (MIME类型),默认值为 text/html(默认不压缩js/css)。(注意:需要压缩的类型都可以通过响应头中的 Content-Type 查看,如 js 类型为 Content-Type:application/javascript,需要压缩 js 时,则这个值必须配置在 gzip_types 中,同时满足其他条件时,就会生效压缩。)

6、此时重启 nginx : .\nginx.exe -s reload,再次访问时如下,没有压缩时响应头中会有 Content-Length:***,压缩后响应头中会有 Content-Encoding:***

Nginx 解决请求跨域 与 配置 gzip 压缩

如上所示:Content-Encoding:gzip 表示内容为 gzip 压缩。

注意:如上所示为下载的最新版 JQuery-3.4.0.js,大小为 273KB,所以上面配置 gzip_min_length 故意设置为了 100,如果设置成 gzip_min_length 1000;,那么就不会对它进行压缩了。

nginx 常用命令

start nginx.exe //启动
nginx.exe -s reload //重启
nginx.exe -s stop //快速停止
nginx.exe -s quit //完整有序停止

没配置环境变量时,在 nginx.exe 所在目录下使用命令行即可。