一    ngx_http_map_module模块

1) map 指令是由 'ngx_http_map_module 模块'提供的,'默认'情况下nginx 会'安装'该模块

2) map 的主要作用是'创建自定义变量',通过使用 nginx 的'内置'变量,去'匹配'某些特定规则;

备注:只有'result_var'引用的时候,才会寻找这个'map'

map nginx 使用没有生效 nginx map模块_Access

(1)总述

说明: string["已有变量"]可以是'变量(动态提供了无限可能)',也可以是'字符串'

map nginx 使用没有生效 nginx map模块_map指令_02

意外之喜: map的'源变量'可以是'组合形式'

map '${var1}${var2}'  $result {
  ... 
}

对比:if'只能'使用'某一个变量'判断

①  理解新变量的值取决于多个源变量场景

细节: '源变量'必须是'已经存在的',不然'怎么做'适配

源变量: 即 map指令 后面的'那个string(已有变量)'

map nginx 使用没有生效 nginx map模块_map指令_03

map nginx 使用没有生效 nginx map模块_Access_04

②   map块何时被执行

map nginx 使用没有生效 nginx map模块_nginx_05

map性能问题

map nginx 使用没有生效 nginx map模块_map nginx 使用没有生效_06

(2)源值的形式

map nginx 使用没有生效 nginx map模块_字符串_07

①  源值是裸字符串,不包含特殊字符串

源值如果是'裸字符串',则'不区分'大小写

map nginx 使用没有生效 nginx map模块_nginx_08

map nginx 使用没有生效 nginx map模块_字符串_09

②  源值是裸值,包含特殊字符

map nginx 使用没有生效 nginx map模块_Access_10

③  源值以~和~*开头,只做正则表达式匹配

说明:最经常遇到的就是'正则域名'中需要'\.'转义

map nginx 使用没有生效 nginx map模块_Access_11

④  源值以~和~*开头,正则表达式匹配后补获

说明: 这种方式,一次创建'多个'变量

map nginx 使用没有生效 nginx map模块_map nginx 使用没有生效_12

 nginx的命名补获 

1)方式1

map nginx 使用没有生效 nginx map模块_Access_13

map nginx 使用没有生效 nginx map模块_Access_14

2)方式2  重点掌握

map nginx 使用没有生效 nginx map模块_nginx_15

map nginx 使用没有生效 nginx map模块_nginx_16

(3) 结果值形式

高级: 结果值是'$uri'形式

map nginx 使用没有生效 nginx map模块_字符串_17

map nginx 使用没有生效 nginx map模块_字符串_18

map nginx 使用没有生效 nginx map模块_map指令_19

map nginx 使用没有生效 nginx map模块_Access_20

补充

(4)特殊参数

①  default value

map nginx 使用没有生效 nginx map模块_字符串_21

map nginx 使用没有生效 nginx map模块_map nginx 使用没有生效_22

map $source_var target_var {
    case "1";
    default "";
}

+++++++  "等价形式"  +++++++

map $source_var target_var {
    case "1";
}

②  hostnames指令

应用场景: $http_host、$host变量

map nginx 使用没有生效 nginx map模块_nginx_23

1)案例

map nginx 使用没有生效 nginx map模块_map nginx 使用没有生效_24

map nginx 使用没有生效 nginx map模块_nginx_25

2)优先级小结

map nginx 使用没有生效 nginx map模块_字符串_26

map nginx 使用没有生效 nginx map模块_字符串_27

include

map nginx 使用没有生效 nginx map模块_map指令_28

map nginx 使用没有生效 nginx map模块_字符串_29

细节点: 注意include'文件'的形式和'相对路径'

map nginx 使用没有生效 nginx map模块_字符串_30

map nginx 使用没有生效 nginx map模块_Access_31

map nginx 使用没有生效 nginx map模块_map nginx 使用没有生效_32

④   volatile

map nginx 使用没有生效 nginx map模块_nginx_33

map nginx 使用没有生效 nginx map模块_Access_34

应用场景

++++++++++++  'map的应用场景'  ++++++++++++

 1) 想象'编程语言'中的'switch { case: }'场景

 2) 或者if {} else if {} else {}场景,这里都可以'转换'为map

 3) map与'nginx log_format if=' 做'debug'判断

 4) iframe嵌套,通过'map $http_referer $result'判断,另外通过改变'$result'做'例外'判断

 5) nginx配置解决'低版本 Chrome浏览器'SameSite跨域'兼容性'问题

源变量必须是'已有变量'

强调:和'内置变量'才能玩出'花样'

说明:'string'一般我们会用'nginx的内置变量'来代替,不会直接写'裸值',便于'动态'

补充:已知'set、map、正则命名补获(?<name>.*)'三种方式来'设置变量'

map nginx 使用没有生效 nginx map模块_Access_35

补充

关注点:chrome的'版本'跟SameSite的关系 --> 'Chrome/81.0.4044.138'

nginx配置解决Chrome浏览器SameSite跨域问题     Chrome同站策略

nginx 为chrome客户端请求加SameSite=None;Secure

二   案例讲解

①    简单案例

map $args $foo {
    default 0;
    debug   1;
}

变量解读:$args 是nginx'内置[inner]'变量,$foo是我们自定义的'普通[common]'变量

附加:$args 这个变量等于'请求行中(GET请求)的参数',例如foo=123&bar=wzj;

效果:如果 $args '匹配到 debug' 那么 $foo 的值会'被设为 1 '

ps: 如果 $args 一个都'匹配不到' $foo 就是'default 定义的值',在这里就是 0

大白话:类似于一个'if/else'判断,设置'变量值'

②  案例一:nginx开启websocket代理功能

http {
    ...
    # 是否是'websocket'
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''  close;
    }

    location  /v1/kind {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        # proxy_set_header Connection "upgrade"; -->对比二者的区别?
        ...
    }
}

websocket协议为什么HTTP Upgrade的时候需要Connection: upgrade ?

WebSocket为什么需要Connection和Upgrade两个header?

nginx支持websocket反向代理

③  案例二:后端代理切不同的版本、或者兰绿发布

upstream upstream_k8s {
    server ip:port;
    ...
}

upstream upstream_default {
    server ip:port
}

# zone是存储区域
limit_req_zone $client_real_ip zone=A:100m rate=1000r/s
limit_conn_zone $client_real_ip zone=B:100m;

# 变量必须是nginx的内置变量吗? -->'非必须'

map $COOKIE_k8s_flag $k8s {
   # 等待匹配的字符串可以不加引号
   k8s1    upstream_k8s;
   # 说明:upstream_default和upstream_k8s与前面的映射
   deafult upstream_default; 
}


location /k8s {
    limit_req zone=A burst=10000 nodelay;
    limit_conn B 1000;
    # 注意引入方式
    proxy_pass https://${k8s};
    ...
}

④  案例三:跨域名访问

# 这些配置可以写在 http{} 或者 server{} 都是'支持'的
add_header Access-Control-Allow-Origin "http://www.wzj.com";
add_header Access-Control-Allow-Methods "POST, GET, PUT, OPTIONS, DELETE";
add_header Access-Control-Max-Age "3600";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";

1) 上面的配置'只允许' http://www.wzj.com 跨域访问

2) 如果要支持'所有域名'都可以跨域调用该站, 不过'不推荐'这样做,因为'不安全'

add_header Access-Control-Allow-Origin "*";

++++++++++++++"不想允许所有,但是又需要允许多个域名,那么就需要用到 map"++++++++++++++

需求: 使用 map 来实现允许'多个域名跨域'访问的问题

map $http_origin $corsHost {
    default 0;
    "~http://www.wzj.com" http://www.wzj.com;
    "~http://" http://harbor.wzj.com;
    "~http://nginx.wzj.com" http://nginx.wzj.com;
}

server{
    listen 80;
    server_name www.wzj.com;
    root /nginx;
    location /
    {
        add_header Access-Control-Allow-Origin $corsHost;
        ...
    }
}

⑤  map相关调试

需求:使用源变量'通常是 nginx 内置变量'匹配一些规则,创建自定义变量,然后在页面输出. 这通常在'调试'的时候非常有用

复制代码
http {
map $uri $match {
    # 说明:default可以'省略'
    ~^/www/(.*) http://www.wzj.com/;
}
server {
    listen       8080;
    server_name  harbor.wzj.com;

    location /www {
            default_type text/plain;
            echo uri: $uri;
            echo match: $match;
            echo capture: $1;
            echo new: $match$1;
    }

细节:openresty自带'echo'模块

map相关参考 

⑥  map指令的阶段问题

map nginx 使用没有生效 nginx map模块_Access_36

⑦  典型的应用场景

+++++++++++++++++ "后续再遇到"会慢慢补充  +++++++++++++++++

1) 特殊'版本'的agent才允许访问

2)nginx自身通过XFF获取'真实ip' -->创建其它'新变量'

3) 'websocket'配置

4)跨域