暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

nginx配置之location的应用

炉门点饭 2022-05-25
495

背景

本次分享来自于一次阿里云域名备案要求,需要给我们的原来没有配置”正经“首页的api域名增加一个首页,本来应该是一个很简单的需求,接到需求的时候就想到只需要简单nginx配置一下就行~~~没想到。。。请看下面👇

现实

这次需要配置的域名对应的GO服务路由其实很简单。。也许就是因为他的简单。。。所以才有了这次不那么简单的nginx配置吧

下面就是全部go的配置

    beego.Get("/"func(ctx *context.Context) {
        //ctx.Redirect( 301,"https://www.m***ji.com")//本来是想做个重定向的,但这个样好像就不是我们想要的满足备案要求了,所以最后就没改了。
        retData := util.RetData{Code: 200, Msg: "Hello"}
        ctx.Output.JSON(retData, truefalse)
    })

    beego.Router("/api/v1/xx1", &controllers.XX1Controller{}, "*:Run")
    beego.Router("/api/v1/xx2", &controllers.XX2Controller{}, "*:Run")
    beego.Router("/:url([a-zA-z0-9]{6,})", &controllers.xx3Controller{}, "*:Run")

    beego.Get("/*"func(ctx *context.Context) {
        retData := util.RetData{Code: 404, Msg: "Not Found"}
        ctx.Output.JSON(retData, truefalse)
    })

复制

实现

随手而来的是这样的

server {
    listen  80;
    server_name test.xxx.pub;
    root /home/test/projects/xx/;
    index  index.html index.html;

    access_log /home/test/projects/xx/access.log;
    error_log /home/test/projects/xx/error.log;

    location = / {
        alias /home/test/projects/xx/;
        index  index.html index.html;
    }
    location / {
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host            $http_host;

        proxy_pass http://127.0.0.1:8099;
    }
}

复制

请求网页返回结果

从图片可以看出返回了404应该是进入到了go服务里面了,匹配到了上面相应的路由

    beego.Get("/*"func(ctx *context.Context) {
        retData := util.RetData{Code: 404, Msg: "Not Found"}
        ctx.Output.JSON(retData, truefalse)
    })

复制

这样看来nginx配置应该是有问题

于是为了验证 ”location = “是有被使用的,所以在后面加上了return 404这个状态码

server {
    listen  80;
    server_name test.xx.pub;
    root /home/test/projects/xx/;
    index  index.html index.html;

    access_log /home/test/projects/xx/access.log;
    error_log /home/test/projects/xx/error.log;

    location = / {
        alias /home/test/projects/xx/;
        index  index.html index.html;
        return 404;
    }
    location / {
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host            $http_host;

        proxy_pass http://127.0.0.1:8099;
    }
}

复制

页面返回nginx的404状态页,也就是说请求是有被 ”location = “ 匹配到的,那为什么上面没有增加return 404这个状态码的请求返回的值进到了go项目呢

我们快进一下,修改为下面这两段代码,打印一下请求的uri,或许能有一些线索

第一次先修改这增加返回uri
location = / {
        alias /home/test/projects/xx/;
        index  index.html index.html;
        default_type text/html;
        return 200 $uri;
    }

下一次测试修改这段
 location / {
        default_type text/html;
        return 200 $uri;
}

复制

第一段配置返回值 uri 是斜杠 /
,第二段配置返回值同样是/
。看到这里也就不难理解刚才代码为什么已经使用了 location =
但还是进到go服务里面而不是返回我们想要它返回index.html路径了,因为它匹配完 location =
 后 还匹配到了 location
,从而导致和我们想要的结果不一致。

当然,这个过程我们还尝试了很多种不同的写法,但都没办法达到我们想的结果,最后使用rewrite解决了我们的问题。

server {
    listen  80;
    server_name test.xx.pub;

    access_log /home/test/projects/xx/access.log;
    error_log /home/test/projects/xx/error.log;

    if ($uri = '/') {
        rewrite .* http://test.xx.pub/index.html? permanent;#这里增加 ? 是为了让请求后面不带参数,因为这只是首页
    }

    location = /index.html {
        root /home/test/projects/xx/;
        index index.html;
    }

    location / {
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host            $http_host;

        proxy_pass http://127.0.0.1:8099;
    }
}

复制

号外(内容来源互联网)

location 匹配简介

从功能看,rewrite 和 location 似乎很像,都能实现跳转,主要区别在于 rewrite 是在同一域名内更改获取资源的路径,而 location 是对一类路径做控制访问或反向代理,还可以 proxy_pass 到其他机器。

匹配规则格式

①精准匹配 location = {...}

②一般匹配 location {...}

③正则匹配 location ~ {...}

常用的匹配规则

= :进行普通字符精确匹配,也就是完全匹配。

^~ :表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其它 location。

~ :区分大小写的匹配。

~* :不区分大小写的匹配。

!~ :区分大小写的匹配取非。

!~* :不区分大小写的匹配取非。

location = / {
   #规则A
}
location = /aa {
   #规则B
}
location ^~ /aa/ {
   #规则C
}
location ~ \.(gif|jpg|png)$ {
   #规则D
}
location ~* \.png$ {
   #规则E
}
location !~ \.html$ {
   #规则F
}
location !~* \.html$ {
   #规则G
}
location / {
   #规则H
}

复制

匹配的优先级

首先精确匹配 = 其次前缀匹配 ^~ 再其次是按文件中顺序的正则匹配 * 然后匹配不带任何修饰的前缀匹配(一般匹配) 最后是交给 通用匹配

示例

(1)location = / {}
=为精确匹配 / ,主机名后面不能带任何字符串,比如访问 / 和 /data,则 / 匹配,/data 不匹配
再比如 location = /abc,则只匹配/abc ,/abc/或 /abcd不匹配。若 location  /abc,则即匹配/abc 、/abcd/ 同时也匹配 /abc/。

(2)location / {}
因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 比如访问 / 和 /data, 则 / 匹配, /data 也匹配,
但若后面是正则表达式会和最长字符串优先匹配(最长匹配)

(3)location /documents/ {}
匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条

(4)location /documents/abc {}
匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条

(5)location ^~ /images/ {}
匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条

(6)location ~* \.(gif|jpg|jpeg)$ {}
匹配所有以 gif、jpg或jpeg 结尾的请求
然而,所有请求 /images/ 下的图片会被 location ^~ /images/ 处理,因为 ^~ 的优先级更高,所以到达不了这一条正则

(7)location /images/abc {}
最长字符匹配到 /images/abc,优先级最低,继续往下搜索其它 location,会发现 ^~ 和 ~ 存在

(8)location ~ /images/abc {}
匹配以/images/abc 开头的,优先级次之,只有去掉 location ^~ /images/ 才会采用这一条

(9)location /images/abc/1.html {}
匹配/images/abc/1.html 文件,如果和正则 ~ /images/abc/1.html 相比,正则优先级更高

复制


文章转载自炉门点饭,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论