7

震惊--Nginx的map指令还能这样用 - 白--茶

 2 years ago
source link: https://www.cnblogs.com/chaizhenhua/p/16247460.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

map指令简单介绍

当然这里写的都是官方文档是已经写过的,我简单抄一下哈。

map指令来自于 ngx_http_map_module 模块,提供的核心能力是 基于一个变量创建一个新变量,大概是这意思。

语法: 只能配置在http块内
map string $variable {...}

直接看这个语法好像看不出来它能干什么,所以官方文档上给了几个例子:

map $http_host $name {
    hostnames;

    default       0;

    example.com   1;
    *.example.com 1;
    example.org   2;
    *.example.org 2;
    .example.net  3;
    wap.*         4;
}

解析一下上面👆这个例子的意思👇:

map: 关键字,开辟一段内存空间声明一个map

$http_host: 获取host请求头:eg: www.baidu.com

$name: 新变量,具体取值是什么取决于结构体内的映射关系

结构体内的数据解析:
    hostnames:
    - 官方文档给出的解释是:允许用前缀或者后缀掩码指定域名作为源变量值。这个参数必须写在值映射列表的最前面。

    读都能读的懂,字也都认识,但是怎么感觉好像还是不太懂呢,又没有同感?于是我测试了一下,其实就是你想用下面那种泛域名来匹配host的话就加一下这个参数, 否则是达不到预期效果的。

    default 0; :匹配不到符合条件的数据时 则$name 这个变量就取默认值 0

知道了这之后我能用它来做什么呢?看实际应用的例子

map指令的实践使用

1. 基于cookie做多环境分流

一般中大型公司都会有多套测试环境,对于多环境的访问可能最容易想到的就是对应多个域名,这方法当然可以,但是不优雅,维护多个域名太累。为了偷懒,我们用了一个域名,使用不同的cookie来转发相应的流量到相应的环境。

如何实现?

    map $cookie_cl_env_num $cl_backend_map {
        default   1.1.1.1:80;
        dev-01    upstream_dev-01;
        dev-02    upstream_dev-02;
        dev-03    upstream_dev-03;
        test-01   upstream_test-01;
        test-02   upstream_test-02;
        test-03   upstream_test-03;
        test-04   upstream_test-04;
        test-05   upstream_test-05;
        test-06   upstream_test-06;
        test-07   upstream_test-07;
        test-08   upstream_test-08;
        test-09   upstream_test-09;
        test-10   upstream_test-10;
        test-11   upstream_test-11;
        test-12   upstream_test-12;
        test-13   upstream_test-13;
        test-14   upstream_test-14;
        test-15   upstream_test-15;
    }

    # 随便写一个
    upstream upstream_test-14 {
        server 2.2.2.2:80;
    }

    # 局部实现写一下
    location / {
        pass_pass http://$cl_backend_map;
    }

    # 请求
    curl --cookie "cl_env_num=test-15" a.test.com/api/v1/hahaha

这不就实现了嘛,很方便哈。仅提供思路!当然也可以使用其他变量来分流 UA|args ...

2. 做安全的多域名跨域访问

跨域访问一般情况下我们都会直接设置 * 允许所有跨域访问。但是难免会有一些对安全性要求较高的业务不允许这样,那么对于域名比较多的安全跨域配置,也可以使用map来实现。

map $http_origin $allow_origin {
    ~http://www.baidu.com http://www.baidu.com;
    ~http://m.baidu.com   http://m.baidu.com;
    ~http://a.baidu.com   http://a.baidu.com;
    default               deny;
}

server {
    listen 80;
    server_name www.baidu.com;

    location / {
        ...
        add_header Access-Control-Allow-Origin $allow_origin;
        ...
    }
}

仅提供思路哈,具体情况可以再优化

当然还有很多场景都可以用到, 无法一一列举, 自己能够根据需求和场景灵活运用是最好的。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK