20200529golang&nginx

May 29, 2020

使用docker/golang 执行本地golang 服务

cd $工作目录

docker run --rm -it --name go-http-demo -v $PWD:/go/src/example.com/go-http-demo -p 14500:8080 golang

弄懂 Nginx location

我遇到的问题

之前服务器已使用有a.ahuang.ml 域名的A服务,仅提供后台api 接口;然后再做B服务时,由于理念很接近,还得使用a.ahuang.ml 的子域名,所以规划好location 就很重要。

我的本地解决测试方案

当前给出我改好的location 样式:

  1. 首先设定好本地的test 域名 DNS 转向本地:
1
2
3
sudo vim /etc/host
输入 127.0.0.1 test.ahuang.ml
vim ~/conf/ahuang.conf
  1. 书写~/conf/ahuang.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
~/conf/ahuang.conf

server {
listen 80;
server_name test.ahuang.ml;
client_max_body_size 500M;
location / {
return 800;
}
location ~ ^/(api|evidence/) {
return 900;
}
}
  1. 执行启动nginx

docker run --rm -p 127.0.0.1:8888:80 --name mynginx -v $PWD/conf:/etc/nginx/conf.d nginx

  1. 测试

    curl http://test.ahuang.ml:8888/api # 返回900
    curl http://test.ahuang.ml:8888/evidence/xx # 返回900
    curl http://test.ahuang.ml:888/abc # 返回800

读参考文章注意点

完全参考掘金文章

推荐直接参考原文章

location修饰符类型

location 支持的语法 location [=|~|~*|^~|@] pattern { ... }

「=」 修饰符: 要求路径完全匹配

1
2
3
4
server {
server_name website.com;
location = /abcd {}
}
  • http://website.com/abcd 匹配

  • http://website.com/ABCD 可能会匹配,也可能不匹配,取决于操作系统的文件系统是否大小写敏感(case-sensitive)。ps: MAC 默认是大小写不敏感的。

  • http://website.com/abcd?param1*param2 匹配

  • http://website.com/abcd/ 不匹配

  • http://website.com/abcde 不匹配

「~」 修饰符: 区分大小写的正则匹配

1
2
3
4
server {
server_name website.com;
location ~ ^/abcd$ {}
}

^/abcd$ 这个正则表达式标识字符串必须以 /开始,以$结束,中介必须是abcd

  • http://website.com/abcd 匹配

  • http://website.com/ABCD 不匹配

  • http://website.com/abcd?param1&param2 匹配

  • http://website.com/abcd/ 不匹配

  • http://website.com/abcde 不匹配

「~*」 修饰符: 不区分大小写的正则匹配

1
2
3
4
server {
server_name website.com;
location ~* ^/abcd$ {}
}
  • http://website.com/abcd 匹配

  • http://website.com/ABCD 匹配

  • http://website.com/abcd?param1&param2 匹配

  • http://website.com/abcd/ 不匹配

  • http://website.com/abcde 不匹配

「^~」 修饰符: 前缀匹配

如果该location 是最佳的匹配,那么对于匹配这个location 的字符串,该修饰符不再进行正则表达式的检测。注意,这不是一个正则表达式匹配,他的目的是优先于正则表达式的匹配

路径查找顺序及优先级

当有多条location 规则时,nginx 有一套比较复杂的规则,优先级如下:

  • 精确匹配 =

  • 前缀匹配 ^~ 立刻停止后续的正则搜索

  • 按文件中顺序的正则匹配 ~ 或 ~*

  • 匹配不带任何修饰的前缀匹配

案例分析

原文章的案例分析非常的给人容易学习

案例1

1
2
3
4
5
6
7
8
9
10
11
server {
server_name website.com;
location /doc {
return 701; # 用这样的方式,可以方便的知道请求到了哪里
}
location ~* ^/document$ {
return 702; # 用这样的方式,可以方便的知道请求到了哪里
}
}
curl -I website.com:8080/document
HTTP/1.1 702

按照上述的规则,第二个会有更高的优先级

案例2

1
2
3
4
5
6
7
8
9
10
server {
server_name website.com;
location /document {
return 701;
}
location ~* ^/document$ {
return 702;
}
}
curl -I website.com:8080/document

第二个匹配了正则表达式,优先级高于第一个普通前缀匹配

案例3

1
2
3
4
5
6
7
8
9
10
11
server {
server_name website.com;
location ^~ /doc {
return 701;
}
location ~* ^/document$ {
return 702;
}
}
curl http://website.com/document
HTTP/1.1 701

第一个前缀匹配^~命中以后不会再搜寻正则匹配,所以会第一个命中

案例4

1
2
3
4
5
6
7
8
9
10
server {
server_name website.com;
location /docu {
return 701;
}
location /doc {
return 702;
}
}
curl -I website.com:8080/document 返回 HTTP/1.1 701,
1
2
3
4
5
6
7
8
9
10
server {
server_name website.com;
location /doc {
return 702;
}
location /docu {
return 701;
}
}
curl -I website.com:8080/document 依然返回 HTTP/1.1 701

前缀匹配下,返回最长匹配的 location,与 location 所在位置顺序无关

案例5

1
2
3
4
5
6
7
8
9
10
11
server {
listen 8080;
server_name website.com;
location ~ ^/doc[a-z]+ {
return 701;
}
location ~ ^/docu[a-z]+ {
return 702;
}
}
curl -I website.com:8080/document 返回 HTTP/1.1 701

把顺序换一下

1
2
3
4
5
6
7
8
9
10
11
server {
listen 8080;
server_name website.com;
location ~ ^/docu[a-z]+ {
return 702;
}
location ~ ^/doc[a-z]+ {
return 701;
}
}
curl -I website.com:8080/document 返回 HTTP/1.1 702

正则匹配是使用文件中的顺序,找到返回